SpringDataJpa多表操作的实现

2022-01-24 0 739
目录

数据库中的表存在着多种关系,一对一,一对多,多对多

Jpa表关系分析步骤

开发过程中会有很多多表的操作,他们之间有着各种关系,在Jpa这种实现来了orm思想的框架中我们可以通过操作实体类来操作数据库,我们来连接下jap如何配置实体类来实现这种功能

  • 确定表之间的关系
  • 在数据库实现两个表的关系
  • 在实体类种描述两个表的关系
  • 配置数据库和实体类的关系映射

关联关系的注解

@OneToOne、@JoinColumn、@ManyToOne、@ManyToMany、@JoinTable、@OrderBy

@JoinColumn定义外键关联的字段名称

@Repeatable(JoinColumns.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JoinColumn {
    //目标表的字段名,必填
    String name() default \"\";
    //本实体的字段名,非必填,默认是本表ID
    String referencedColumnName() default \"\";
    //外键字段是否唯一
    boolean unique() default false;
    //外键字段是否允许为空
    boolean nullable() default true;
    //是否跟随一起新增
    boolean insertable() default true;
    //是否跟随一起更新
    boolean updatable() default true;

    String columnDefinition() default \"\";

    String table() default \"\";

    ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}

用法:@JoinColumn主要配合@OneToOne、@ManyToOne、@OneToMany一起使用,单独使用没有意义。@JoinColumn定义多个字段的关联关系。

@OneToOne一对一关联关系

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToOne {
    //关系目标实体,非必填,默认该字段的类型。
    Class targetEntity() default void.class;
    //cascade级联操作策略
    /*1.CascadeType.PERSIST级联新建
      2.CascadeType.REMOVE级联删除
      3.CascadeType.REFRESH级联刷新
      4.CascadeType.MERGE级联更新
      5.CascadeType.ALL四项全选
      6.默认,关系表不会产生任何影响*/
    CascadeType[] cascade() default {};
    //数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default FetchType.EAGER;
    h()defaultEAGER;//是否允许为空
    boolean optional() default true;
//关联关系被谁维护的。非必填,一般不需要特别指定。//注意:只有关系维护方才能操作两者的关系。被维护方即使设置了维护方属性进行存储也不会更新外键关联。1)mappedBy不能与@JoinColumn或者@JoinTable同时使用。2)mappedBy的值是指另一方的实体里面属性的字段,而不是数据库字段,也不是实体的对象的名字。既是另一方配置了@JoinColumn或者@JoinTable注解的属性的字段名称。
    String mappedBy() default \"\";
    //是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}

用法@OneToOne需要配合@JoinColumn一起使用。

举个例子使用@OneToOne和@JoinColumn注解

分析 一个学生对应一个班级,添加一个学生时同时添加班级

学生类

@Data
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String studentName;

    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = \"grade_id\")
    private Grade grade;
}

班级类

@Data
@Entity
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String gradeName;

   /* @OneToOne(mappedBy = \"grade\")
    private Student student;*/
}

接口

public interface StudentRepository extends JpaRepository<Student,Integer> {
}

测试类

@Test
public void test1(){

    Grade grade = new Grade();
    grade.setGradeName(\"一年级\");
    Student student = new Student();
    student.setStudentName(\"张三\");
    student.setGrade(grade);
    studentRepository.save(student);
}

测试结果

这两个数据我用的一个是配置了一方关联,只在Student类里配置了班级信息,还有一条是配置了双向关联,Grade类里边被注释掉的部分,具体使用哪个,根据具体的业务需求

@OneToMany一对多& @ManyToOne多对一

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
    Class targetEntity() default void.class;
//cascade级联操作策略:(CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH、CascadeType.MERGE、CascadeType.ALL)
    CascadeType[] cascade() default {};
//数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default FetchType.LAZY;
//关系被谁维护,单项的。注意:只有关系维护方才能操作两者的关系。
    String mappedBy() default \"\";
//是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToOne {
    Class targetEntity() default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch() default FetchType.EAGER;

    boolean optional() default true;
}

@OneToMany一对多& @ManyToOne多对一的源码,FetchType一个是FetchType.LAZY;一个是 FetchType.EAGER;

实体类

现在实现一对多的例子,一个班有多个学生,新增班级时新增多个学生

@Entity
@Data
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String gradeName;


    @OneToMany(mappedBy = \"grades\",cascade = CascadeType.ALL)
    private List<Student>  students;

}

@Entity
@Data
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String studentName;


    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name=\"grades_id\")
    private Grade grades;
}

接口

public interface GradeRepository extends JpaRepository<Grade , Integer> {
}

测试类

@Test
public void test1(){
    Grade grade = new Grade();
    grade.setGradeName(\"一年级一班\");
    ArrayList<Student> students = new ArrayList<>();

    Student student = new Student();
    student.setStudentName(\"张三\");
    student.setGrades(grade);

    Student student1 = new Student();
    student1.setStudentName(\"李四\");
    student1.setGrades(grade);

    students.add(student);
    students.add(student1);
    
    grade.setStudents(students);


    gradeRepository.save(grade);

}

结果

@OrderBy关联查询的时候的排序

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OrderBy {

    /***要排序的字段,格式如下:
    orderby_list::=orderby_item[,orderby_item]
    orderby_item::=[property_or_field_name][ASC|DESC]
    字段可以是实体属性,也可以数据字段,默认ASC。*/
    String value() default \"\";
}
@OneToMany(mappedBy = \"grades\",cascade = CascadeType.ALL)
@OrderBy(\"studentName DESC \")
private List<Student>  students;

@JoinTable关联关系表

@ManyToMany多对多

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToMany {
    Class targetEntity() default void.class;

    CascadeType[] cascade() default {};

    FetchType fetch() default FetchType.LAZY;

    String mappedBy() default \"\";
}

@ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单向双向之分,单项双向和注解没有关系,只看实体类之间是否相互引用。主要注意的是当用到@ManyToMany的时候一定是三张表。

a案例

一个年级有多个老师,一个老师管多个年级

实体类

@Entity
@Data
public class Grade {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer gradeid;
    private String gradeName;
    //配置年级和老师之间的多对多关系
    //1.声明多对多的关系@ManyToMany(targetEntity = Teacher.class)
    //2.配置中间表 
    /* @JoinTable(name = \"grade_teacher\", 中间表表名
            joinColumns = @JoinColumn(name = \"grade_id\" 外键名
            ,referencedColumnName = \"gradeid\"参照的主表的主键名
            ), 
            中间表字段名,在当前表的外键
            inverseJoinColumns = @JoinColumn(name = \"tecacher_id\",referencedColumnName = \"teacherid\"))
            */
            
            
    @ManyToMany(targetEntity = Teacher.class,cascade = CascadeType.ALL)//对方的实体字节码
    //中间表名,
    @JoinTable(name = \"grade_teacher\",
    //外键名,
            joinColumns = @JoinColumn(name = \"grade_id\",referencedColumnName = \"gradeid\"),
            inverseJoinColumns = @JoinColumn(name = \"tecacher_id\",referencedColumnName = \"teacherid\"))
    private List<Teacher> teachers;
}
@Data
@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer teacherid;
    private String  teacherName;

    @ManyToMany(mappedBy = \"teachers\")
    private List<Grade> grades;
}

接口

public interface GradeRepository extends JpaRepository<Grade , Integer> {
}

测试类

@Test
@Transactional
@Commit()
public void test2(){
    //配置两个年级
    Grade grade = new Grade();
    grade.setGradeName(\"一年级\");
    Grade grade2 = new Grade();
    grade2.setGradeName(\"二年级\");

    //创建3个老师
    Teacher teacher = new Teacher();
    teacher.setTeacherName(\"张老师\");
    Teacher teacher2 = new Teacher();
    teacher2.setTeacherName(\"王老师\");
    Teacher teacher3 = new Teacher();
    teacher3.setTeacherName(\"李老师\");

    //给一年级赛3个老师
    ArrayList<Teacher> teachers = new ArrayList<>();
    teachers.add(teacher);
    teachers.add(teacher2);
    teachers.add(teacher3);
    grade.setTeachers(teachers);


    //给2年级赛2个老师
    ArrayList<Teacher> teachers1 = new ArrayList<>();
    teachers1.add(teacher2);
    teachers1.add(teacher3);
    grade2.setTeachers(teachers1);

    gradeRepository.save(grade);
    gradeRepository.save(grade2);
}

测试结果

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 SpringDataJpa多表操作的实现 http://www.20zxx.cn/297558/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务