SpringDataJpa多表操作的實現(xiàn)
數(shù)據(jù)庫中的表存在著多種關(guān)系,一對一,一對多,多對多
Jpa表關(guān)系分析步驟
開發(fā)過程中會有很多多表的操作,他們之間有著各種關(guān)系,在Jpa這種實現(xiàn)來了orm思想的框架中我們可以通過操作實體類來操作數(shù)據(jù)庫,我們來連接下jap如何配置實體類來實現(xiàn)這種功能
- 確定表之間的關(guān)系
- 在數(shù)據(jù)庫實現(xiàn)兩個表的關(guān)系
- 在實體類種描述兩個表的關(guān)系
- 配置數(shù)據(jù)庫和實體類的關(guān)系映射
關(guān)聯(lián)關(guān)系的注解
@OneToOne、@JoinColumn、@ManyToOne、@ManyToMany、@JoinTable、@OrderBy
@JoinColumn定義外鍵關(guān)聯(lián)的字段名稱
@Repeatable(JoinColumns.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface JoinColumn { //目標(biāo)表的字段名,必填 String name() default ""; //本實體的字段名,非必填,默認(rèn)是本表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定義多個字段的關(guān)聯(lián)關(guān)系。
@OneToOne一對一關(guān)聯(lián)關(guān)系
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface OneToOne { //關(guān)系目標(biāo)實體,非必填,默認(rèn)該字段的類型。 Class targetEntity() default void.class; //cascade級聯(lián)操作策略 /*1.CascadeType.PERSIST級聯(lián)新建 2.CascadeType.REMOVE級聯(lián)刪除 3.CascadeType.REFRESH級聯(lián)刷新 4.CascadeType.MERGE級聯(lián)更新 5.CascadeType.ALL四項全選 6.默認(rèn),關(guān)系表不會產(chǎn)生任何影響*/ CascadeType[] cascade() default {}; //數(shù)據(jù)獲取方式EAGER(立即加載)/LAZY(延遲加載) FetchType fetch() default FetchType.EAGER; h()defaultEAGER;//是否允許為空 boolean optional() default true; //關(guān)聯(lián)關(guān)系被誰維護(hù)的。非必填,一般不需要特別指定。//注意:只有關(guān)系維護(hù)方才能操作兩者的關(guān)系。被維護(hù)方即使設(shè)置了維護(hù)方屬性進(jìn)行存儲也不會更新外鍵關(guān)聯(lián)。1)mappedBy不能與@JoinColumn或者@JoinTable同時使用。2)mappedBy的值是指另一方的實體里面屬性的字段,而不是數(shù)據(jù)庫字段,也不是實體的對象的名字。既是另一方配置了@JoinColumn或者@JoinTable注解的屬性的字段名稱。 String mappedBy() default ""; //是否級聯(lián)刪除。和CascadeType.REMOVE的效果一樣。兩種配置了一個就會自動級聯(lián)刪除 boolean orphanRemoval() default false; }
用法@OneToOne需要配合@JoinColumn一起使用。
舉個例子使用@OneToOne和@JoinColumn注解
分析 一個學(xué)生對應(yīng)一個班級,添加一個學(xué)生時同時添加班級
學(xué)生類
@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); }
測試結(jié)果
這兩個數(shù)據(jù)我用的一個是配置了一方關(guān)聯(lián),只在Student類里配置了班級信息,還有一條是配置了雙向關(guān)聯(lián),Grade類里邊被注釋掉的部分,具體使用哪個,根據(jù)具體的業(yè)務(wù)需求
@OneToMany一對多& @ManyToOne多對一
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface OneToMany { Class targetEntity() default void.class; //cascade級聯(lián)操作策略:(CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH、CascadeType.MERGE、CascadeType.ALL) CascadeType[] cascade() default {}; //數(shù)據(jù)獲取方式EAGER(立即加載)/LAZY(延遲加載) FetchType fetch() default FetchType.LAZY; //關(guān)系被誰維護(hù),單項的。注意:只有關(guān)系維護(hù)方才能操作兩者的關(guān)系。 String mappedBy() default ""; //是否級聯(lián)刪除。和CascadeType.REMOVE的效果一樣。兩種配置了一個就會自動級聯(lián)刪除 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多對一的源碼,F(xiàn)etchType一個是FetchType.LAZY;一個是 FetchType.EAGER;
實體類
現(xiàn)在實現(xiàn)一對多的例子,一個班有多個學(xué)生,新增班級時新增多個學(xué)生
@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); }
結(jié)果
@OrderBy關(guān)聯(lián)查詢的時候的排序
@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] 字段可以是實體屬性,也可以數(shù)據(jù)字段,默認(rèn)ASC。*/ String value() default ""; }
@OneToMany(mappedBy = "grades",cascade = CascadeType.ALL) @OrderBy("studentName DESC ") private List<Student> students;
@JoinTable關(guān)聯(lián)關(guān)系表
@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一樣也有單向雙向之分,單項雙向和注解沒有關(guān)系,只看實體類之間是否相互引用。主要注意的是當(dāng)用到@ManyToMany的時候一定是三張表。
a案例
一個年級有多個老師,一個老師管多個年級
實體類
@Entity @Data public class Grade { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer gradeid; private String gradeName; //配置年級和老師之間的多對多關(guān)系 //1.聲明多對多的關(guān)系@ManyToMany(targetEntity = Teacher.class) //2.配置中間表 /* @JoinTable(name = "grade_teacher", 中間表表名 joinColumns = @JoinColumn(name = "grade_id" 外鍵名 ,referencedColumnName = "gradeid"參照的主表的主鍵名 ), 中間表字段名,在當(dāng)前表的外鍵 inverseJoinColumns = @JoinColumn(name = "tecacher_id",referencedColumnName = "teacherid")) */ @ManyToMany(targetEntity = Teacher.class,cascade = CascadeType.ALL)//對方的實體字節(jié)碼 //中間表名, @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("二年級"); //創(chuàng)建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); }
測試結(jié)果
到此這篇關(guān)于SpringDataJpa多表操作的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringDataJpa多表操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot采用Dynamic-Datasource方式實現(xiàn)多JDBC數(shù)據(jù)源
在某些情況下,如果我們需要配置多個數(shù)據(jù)源,本文主要介紹了SpringBoot采用Dynamic-Datasource方式實現(xiàn)多JDBC數(shù)據(jù)源,具有一定的參考價值,感興趣的可以了解一下2023-10-10關(guān)于Filter中獲取請求體body后再次讀取的問題
這篇文章主要介紹了關(guān)于Filter中獲取請求體body后再次讀取的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03springboot2學(xué)習(xí)世界著名程序springboot開發(fā)體驗
這篇文章主要為大家介紹了世界著名程序springboot開發(fā)體驗,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05使用注解解決ShardingJdbc不支持復(fù)雜SQL方法
這篇文章主要為大家介紹了使用注解解決ShardingJdbc不支持復(fù)雜SQL方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Java實現(xiàn)解析JSON大文件JsonReader工具詳解
這篇文章主要介紹了Java實現(xiàn)解析JSON大文件的工具JsonReader使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01java 使用BigDecimal進(jìn)行貨幣金額計算的操作
這篇文章主要介紹了java 使用BigDecimal進(jìn)行貨幣金額計算的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02