SpringDataJpa多表操作的實(shí)現(xiàn)
數(shù)據(jù)庫(kù)中的表存在著多種關(guān)系,一對(duì)一,一對(duì)多,多對(duì)多
Jpa表關(guān)系分析步驟
開發(fā)過(guò)程中會(huì)有很多多表的操作,他們之間有著各種關(guān)系,在Jpa這種實(shí)現(xiàn)來(lái)了orm思想的框架中我們可以通過(guò)操作實(shí)體類來(lái)操作數(shù)據(jù)庫(kù),我們來(lái)連接下jap如何配置實(shí)體類來(lái)實(shí)現(xiàn)這種功能
- 確定表之間的關(guān)系
- 在數(shù)據(jù)庫(kù)實(shí)現(xiàn)兩個(gè)表的關(guān)系
- 在實(shí)體類種描述兩個(gè)表的關(guān)系
- 配置數(shù)據(jù)庫(kù)和實(shí)體類的關(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 ""; //本實(shí)體的字段名,非必填,默認(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一起使用,單獨(dú)使用沒(méi)有意義。@JoinColumn定義多個(gè)字段的關(guān)聯(lián)關(guān)系。
@OneToOne一對(duì)一關(guān)聯(lián)關(guān)系
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface OneToOne { //關(guān)系目標(biāo)實(shí)體,非必填,默認(rèn)該字段的類型。 Class targetEntity() default void.class; //cascade級(jí)聯(lián)操作策略 /*1.CascadeType.PERSIST級(jí)聯(lián)新建 2.CascadeType.REMOVE級(jí)聯(lián)刪除 3.CascadeType.REFRESH級(jí)聯(lián)刷新 4.CascadeType.MERGE級(jí)聯(lián)更新 5.CascadeType.ALL四項(xiàng)全選 6.默認(rèn),關(guān)系表不會(huì)產(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)系被誰(shuí)維護(hù)的。非必填,一般不需要特別指定。//注意:只有關(guān)系維護(hù)方才能操作兩者的關(guān)系。被維護(hù)方即使設(shè)置了維護(hù)方屬性進(jìn)行存儲(chǔ)也不會(huì)更新外鍵關(guān)聯(lián)。1)mappedBy不能與@JoinColumn或者@JoinTable同時(shí)使用。2)mappedBy的值是指另一方的實(shí)體里面屬性的字段,而不是數(shù)據(jù)庫(kù)字段,也不是實(shí)體的對(duì)象的名字。既是另一方配置了@JoinColumn或者@JoinTable注解的屬性的字段名稱。 String mappedBy() default ""; //是否級(jí)聯(lián)刪除。和CascadeType.REMOVE的效果一樣。兩種配置了一個(gè)就會(huì)自動(dòng)級(jí)聯(lián)刪除 boolean orphanRemoval() default false; }
用法@OneToOne需要配合@JoinColumn一起使用。
舉個(gè)例子使用@OneToOne和@JoinColumn注解
分析 一個(gè)學(xué)生對(duì)應(yīng)一個(gè)班級(jí),添加一個(gè)學(xué)生時(shí)同時(shí)添加班級(jí)
學(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; }
班級(jí)類
@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> { }
測(cè)試類
@Test public void test1(){ Grade grade = new Grade(); grade.setGradeName("一年級(jí)"); Student student = new Student(); student.setStudentName("張三"); student.setGrade(grade); studentRepository.save(student); }
測(cè)試結(jié)果
這兩個(gè)數(shù)據(jù)我用的一個(gè)是配置了一方關(guān)聯(lián),只在Student類里配置了班級(jí)信息,還有一條是配置了雙向關(guān)聯(lián),Grade類里邊被注釋掉的部分,具體使用哪個(gè),根據(jù)具體的業(yè)務(wù)需求
@OneToMany一對(duì)多& @ManyToOne多對(duì)一
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface OneToMany { Class targetEntity() default void.class; //cascade級(jí)聯(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)系被誰(shuí)維護(hù),單項(xiàng)的。注意:只有關(guān)系維護(hù)方才能操作兩者的關(guān)系。 String mappedBy() default ""; //是否級(jí)聯(lián)刪除。和CascadeType.REMOVE的效果一樣。兩種配置了一個(gè)就會(huì)自動(dòng)級(jí)聯(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一對(duì)多& @ManyToOne多對(duì)一的源碼,F(xiàn)etchType一個(gè)是FetchType.LAZY;一個(gè)是 FetchType.EAGER;
實(shí)體類
現(xiàn)在實(shí)現(xiàn)一對(duì)多的例子,一個(gè)班有多個(gè)學(xué)生,新增班級(jí)時(shí)新增多個(gè)學(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> { }
測(cè)試類
@Test public void test1(){ Grade grade = new Grade(); grade.setGradeName("一年級(jí)一班"); 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)查詢的時(shí)候的排序
@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í)體屬性,也可以數(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多對(duì)多
@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表示多對(duì)多,和@OneToOne、@ManyToOne一樣也有單向雙向之分,單項(xiàng)雙向和注解沒(méi)有關(guān)系,只看實(shí)體類之間是否相互引用。主要注意的是當(dāng)用到@ManyToMany的時(shí)候一定是三張表。
a案例
一個(gè)年級(jí)有多個(gè)老師,一個(gè)老師管多個(gè)年級(jí)
實(shí)體類
@Entity @Data public class Grade { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer gradeid; private String gradeName; //配置年級(jí)和老師之間的多對(duì)多關(guān)系 //1.聲明多對(duì)多的關(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)//對(duì)方的實(shí)體字節(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> { }
測(cè)試類
@Test @Transactional @Commit() public void test2(){ //配置兩個(gè)年級(jí) Grade grade = new Grade(); grade.setGradeName("一年級(jí)"); Grade grade2 = new Grade(); grade2.setGradeName("二年級(jí)"); //創(chuàng)建3個(gè)老師 Teacher teacher = new Teacher(); teacher.setTeacherName("張老師"); Teacher teacher2 = new Teacher(); teacher2.setTeacherName("王老師"); Teacher teacher3 = new Teacher(); teacher3.setTeacherName("李老師"); //給一年級(jí)賽3個(gè)老師 ArrayList<Teacher> teachers = new ArrayList<>(); teachers.add(teacher); teachers.add(teacher2); teachers.add(teacher3); grade.setTeachers(teachers); //給2年級(jí)賽2個(gè)老師 ArrayList<Teacher> teachers1 = new ArrayList<>(); teachers1.add(teacher2); teachers1.add(teacher3); grade2.setTeachers(teachers1); gradeRepository.save(grade); gradeRepository.save(grade2); }
測(cè)試結(jié)果
到此這篇關(guān)于SpringDataJpa多表操作的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringDataJpa多表操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot + jpa實(shí)現(xiàn)刪除數(shù)據(jù)的操作代碼
- Spring?Boot?整合JPA?數(shù)據(jù)模型關(guān)聯(lián)使用操作(一對(duì)一、一對(duì)多、多對(duì)多)
- SpringDataJPA詳解增刪改查操作方法
- Spring?Data?JPA映射自定義實(shí)體類操作
- Springboot使用Spring Data JPA實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作
- SpringBoot集成JPA持久層框架,簡(jiǎn)化數(shù)據(jù)庫(kù)操作
- springboot-jpa的實(shí)現(xiàn)操作
- springboot 之jpa高級(jí)查詢操作
- Springboot JPA級(jí)聯(lián)操作的實(shí)現(xiàn)(一對(duì)一、一對(duì)多、多對(duì)多)
相關(guān)文章
JAVA基本類型包裝類 BigDecimal BigInteger 的使用
Java 中預(yù)定義了八種基本數(shù)據(jù)類型,包括:byte,int,long,double,float,boolean,char,short,接下來(lái)文章小編將向大家介紹其中幾個(gè)類型的內(nèi)容,需要的朋友可以參考下文章2021-09-09springboot結(jié)合easyexcel實(shí)現(xiàn)動(dòng)態(tài)表頭的實(shí)踐
這篇文章主要介紹了springboot結(jié)合easyexcel實(shí)現(xiàn)動(dòng)態(tài)表頭的實(shí)踐,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06Mybatis order by 動(dòng)態(tài)傳參出現(xiàn)的問(wèn)題及解決方法
今天,我正在愉快地CRUD,突然發(fā)現(xiàn)出現(xiàn)一個(gè)Bug,我們來(lái)看看是怎么回事吧!接下來(lái)通過(guò)本文給大家介紹Mybatis order by 動(dòng)態(tài)傳參出現(xiàn)的一個(gè)小bug,需要的朋友可以參考下2021-07-07Java動(dòng)態(tài)線程池插件dynamic-tp集成zookeeper
ZooKeeper是一個(gè)分布式的,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個(gè)開源的實(shí)現(xiàn),是Hadoop和Hbase的重要組件。它是一個(gè)為分布式應(yīng)用提供一致性的軟件,提供的功能包括:配置維護(hù)、域名服務(wù)、分布式同步、組服務(wù)等2023-03-03Java多線程之鎖學(xué)習(xí)(增強(qiáng)版)
這篇文章主要為大家詳細(xì)介紹了Java多線程中鎖的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對(duì)我們了解線程有一定幫助,需要的可以參考一下2023-02-02Java實(shí)現(xiàn)迷你圖書管理系統(tǒng)案例全程
這篇文章主要為大家詳細(xì)介紹了如何利用java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-12-12Java實(shí)現(xiàn)給圖片添加圖片水印,文字水印及馬賽克的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)給圖片添加圖片水印,文字水印及馬賽克的方法,涉及java針對(duì)圖片的讀取、水印添加、馬賽克設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01