1 JPA概述
1.1 JPA是什么
JPA (Java Persistence API) Java持久化API。是一套Sun公司 Java官方制定的ORM 方案,是規范,是標准 ,sun公司自己並沒有實現
關注點: ORM ,標准 概念 (關鍵字)
1.1.1 ORM是什么
ORM(Object Relational Mapping) 對象關系映射。
問:ORM有什么用?
在操作數據庫之前,先把數據表與實體類關聯起來。 然后通過實體類的對象操作(增刪改查)數據庫表,這個就是ORM的行為!
所以:ORM是一個實現使用對象操作數據庫的設計思想!!!
通過這句話,我們知道JPA的作用就是通過對象操作數據庫的,不用編寫sql語句。
1.2 JPA的實現者
既然我們說JPA是一套標准,意味着,它只是一套實現ORM理論的接口。沒有實現的代碼。
那么我們必須要有具體的實現者才可以完成ORM操作功能的實現!
市場上的主流的JPA框架 (實現者)有:
Hibernate (JBoos)、EclipseTop(Eclipse社區)、OpenJPA (Apache基金會)。
其中Hibernate是眾多實現者之中,性能最好的。所以,我們本次教學也是選用Hibernate框架作為JPA的主講框架。
提醒: 學習一個JPA框架,其他的框架都是一樣使用
1.3 JPA的作用是什么(問題)
JPA是ORM的一套標准,既然JPA為ORM而生,那么JPA的作用就是實現使用對象操作數據庫,不用寫SQL!!!.
問題:數據庫是用sql操作的,那用對象操作,由誰來產生SQL?
答:JPA實現框架
2 入門示例
任何框架的學習,都建議從配置流程圖開始。所以我們來一起理解JPA的配置流程圖。
2.1 配置流程圖
|
1. 我們需要一個總配置文件persistence.xml存儲框架需要的信息 (注意,文件名不要寫錯,而且必須放在classpath/META-INF文件夾里面)
2. 我們需要一個Persistence持久類對象來讀取總配置文件,創建實體管理工廠對象
3. 我們需要實體管理工廠獲得數據庫的操作對象實體管理對象EntityManager。
4. 我們通過EntityManager操作數據庫之前,必須要先配置表與實體類的映射關系,從而實現使用對象操作數據庫!!!
2.2 配置步驟說明
第一步:導入包 (不管什么框架,首先要做的事情)
第二步:創建一個總配置文件
第三步:創建一個JPAUtils獲得操作對象EntityManager
第四步:創建一個實體類,並且配置好映射注解
第五步:在總配置文件加載實體類
第六步:測試代碼(需求:插入數據到用戶表)
2.3 配置步驟
需求:編寫一個JPA的項目,插入一條數據到學生信息表。
2.3.1 第一步:創建Maven項目
說明:我們這里是基於hibernate實現的,所以要導入Hibernate的JPA規范包
--使用maven構建的配置--
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.zj</groupId> <artifactId>jpa-demo01-start</artifactId> <version>0.0.1-SNAPSHOT</version>
<dependencies> <!-- hibernate框架 實現 JPA 依賴 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.6.Final</version> </dependency> <!--jdbc驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> </dependencies> </project> |
2.3.2 第二步:創建一個總配置文件
注意:文件必須放在classpath:/META-INF/persistence.xml
說明:Eclipse已經支持了JPA框架,所有不需要配置xsd文件,直接使用
|
配置信息如下:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd "> <persistence-unit name="mysql-jpa"> <!-- 四要素 org.hibernate.cfg.Environment--> <properties> <!-- 如果使用Hibernate實現的JPA,使用的就是Hibernate的環境參數 --> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa" /> <property name="hibernate.connection.username" value="root" /> <property name="hibernate.connection.password" value="root" /> <!--可選配置--> <!--控制台打印sql語句--> <property name="hibernate.show_sql" value="true" /> <!-- 格式化輸出SQL --> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence> |
2.3.3 第三步:封裝JPAUtils工具類
創建一個工具類JPAUtils,獲得操作對象(EntityManager)
package cn.zj.jpa.util;
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence;
public class JPAUtils {
//同一個應用中,應該保證只有一個實例工廠。 public static EntityManagerFactory emf = createEntityManagerFactory();
//1.獲得實體管理工廠 private static EntityManagerFactory createEntityManagerFactory(){ EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysql-jpa"); return emf; }
//2.獲得實體管理類對象 public static EntityManager getEntityManger(){ EntityManager entityManager = emf.createEntityManager(); return entityManager; } } |
2.3.4 第四步:創建映射實體類
創建一個映射的實體類,將JPA的映射注解寫在實體類里面。
package cn.zj.jpa.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;
//1.指定實體類與表名的關系 //@Entity注解,指定該實體類是一個基於JPA規范的實體類 @Entity //@Table注解,指定當前實體類關聯的表 @Table(name="tb_student") public class Student { //@Id注解:聲明屬性為一個OID屬性 @Id //@GeneratedValue注解,指定主鍵生成策略 @GeneratedValue(strategy=GenerationType.IDENTITY) //@Column注解,設置屬性與數據庫字段的關系,如果屬性名和表的字段名相同,可以不設置 @Column(name="stu_id") private Long stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '學生編號', @Column(name="stu_name") private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '學生名字', @Column(name="stu_age") private Integer stuAge;//INT(11) NULL DEFAULT NULL COMMENT '學生年齡', @Column(name="stu_password") private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '登錄密碼',
public Student() { super(); } //補全get、set方法 } |
2.3.5 第五步:在總配置文件中加載映射實體類
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd "> <persistence-unit name="mysql-jpa">
<!-- 加載實體類 基於hibernate框架的JPA已經實現了自動載入映射實體類 ,所以不配置也是可以的。建議還是加上配置。如果不寫容易忽略加載的實體類有哪些 --> <class>cn.zj.jpa.entity.Student</class> <!-- 四要素 org.hibernate.cfg.Environment--> <properties> <!-- 如果使用Hibernate實現的JPA,使用的就是Hibernate的環境參數 --> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa" /> <property name="hibernate.connection.username" value="root" /> <property name="hibernate.connection.password" value="zj" /> <!--可選配置--> <!--控制台打印sql語句--> <property name="hibernate.show_sql" value="true" /> <!-- 格式化輸出SQL --> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence> |
2.3.6 第六步:操作實體類保存數據
創建一個StudentDAOTest類,測試保存一個學生。
package cn.zj.jpa;
import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import org.junit.Test; import cn.zj.jpa.entity.Student; import cn.zj.jpa.util.JPAUtils;
public class StudentDAOTest {
@Test public void persist(){ //1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger(); //2、獲取事物管理器 EntityTransaction transaction = manager.getTransaction(); transaction.begin(); //3、創建實體對象 Student s=new Student(); s.setStuName("張三"); s.setStuAge(18); s.setStuPassword("zj"); //4、保存到數據庫 manager.persist(s); //5、提交事物 transaction.commit(); //6、關閉資源 manager.close(); } } |
測試結果
|
通過操作實體對象保存數據成功!!!
2.4 使用JPA的好處
使用JPA,可以直接使用對象操作數據庫,由框架根據映射的關系生成SQL。不用開發人員編寫。這樣做,開發人員就不用編寫SQL語句了。
問題:這樣有什么好處呢?
答:不同的數據庫的SQL語法是有差異,如果不需要編寫SQL語句。就屏蔽各種數據庫SQL的差異。那么,編寫的代碼就可以一套代碼兼容多種數據庫!!!!
3 JPA實現CRUD
修改StudentDAOTest類,測試crud操作
//通過OID刪除 @Test public void remove(){ //1.獲得實體管理類對象 EntityManager entityManager = JPAUtils.getEntityManger(); //2.打開事務 EntityTransaction transaction = entityManager.getTransaction(); //3.啟動事務 transaction.begin(); //4.創建數據,刪除數據必須使用持久化對象 Student s=entityManager.find(Student.class, 2L);
//5.插入 entityManager.remove(s);; //6。提交 transaction.commit(); //7.關閉 entityManager.close(); }
//更新 @Test public void merge(){ //1.獲得實體管理類對象 EntityManager entityManager = JPAUtils.getEntityManger(); //2.打開事務 EntityTransaction transaction = entityManager.getTransaction(); //3.啟動事務 transaction.begin(); //4.創建數據 Student s=new Student(); s.setStuName("李四"); //更新必須要有一個OID s.setStuId(3L); //5.更新 entityManager.merge(s); //6。提交 transaction.commit(); //7.關閉 entityManager.close();
}
//通過OID獲得數據 @Test public void find(){ //1.獲得實體管理類對象 EntityManager entityManager = JPAUtils.getEntityManger(); //通過OID查詢數據 Student student = entityManager.find(Student.class, 1L); System.out.println(student.getStuName()); entityManager.close(); }
//通過OID獲得數據 @Test public void getReference(){ //1.獲得實體管理類對象 EntityManager entityManager = JPAUtils.getEntityManger(); /** * getReference()和find()方法的區別: * getReference基於懶加載機制,即需要使用對象的時候,才執行查詢。 */ Student student = entityManager.getReference(Student.class, 1L); System.out.println(student.getStuName()); entityManager.close(); } |
4 JPA常用 API說明
4.1 映射注解說明
注解 |
說明 |
@Entity |
聲明該實體類是一個JPA標准的實體類 |
@Table |
指定實體類關聯的表,注意如果不寫表名,默認使用類名對應表名。 |
@Column |
指定實體類屬性對應的表字段,如果屬性和字段一致,可以不寫 |
@Id |
聲明屬性是一個OID,對應的一定是數據庫的主鍵字段 |
@GenerateValue |
聲明屬性(Object ID)的主鍵生成策略 |
@SequenceGenerate |
使用SEQUENCE策略時,用於設置策略的參數 |
@TableGenerate |
使用TABLE主鍵策略時,用於設置策略的參數 |
@JoinTable |
關聯查詢時,表與表是多對多的關系時,指定多對多關聯表中間表的參數。 |
@JoinColumn |
關聯查詢時,表與表是一對一、一對多、多對一以及多對多的關系時,聲明表關聯的外鍵字段作為連接表的條件。必須配合關聯表的注解一起使用 <key> |
@OneToMany |
關聯表注解,表示對應的實體和本類是一對多的關系 |
@ManyToOne |
關聯表注解,表示對應的實體和本類是多對一的關系 |
@ManyToMany |
關聯表注解,表示對應的實體和本類是多對多的關系 |
@OneToOne |
關聯表注解,表示對應的實體和本類是一對一的關系 |
4.2 JPA常用API說明
API |
說明 |
Persistence |
用於讀取配置文件,獲得實體管理工廠 |
EntityManagerFactory |
用於管理數據庫的連接,獲得操作對象實體管理類 |
EntityManager |
實體管理類,用於操作數據庫表,操作對象 |
EntityTransaction |
用於管理事務。開始,提交,回滾 |
TypeQuery |
用於操作JPQL的查詢的 |
Query |
用於操作JPQL的查詢接口,執行沒有返回數據的JPQL(增刪改) |
CriteriaBuilder |
用戶使用標准查詢接口 Criteria查詢接口 |
5 JPA多表關聯查詢
多個關聯查詢作用(導航查詢):就是實現使用一個實體類對象查詢多個表的數據。
配置多表聯系查詢必須有兩個步驟;
(1)、在實體類里面建立表與表之間的關系。
(2)、在實體類配置關聯關系,JPA使用注解配置
多表關聯的E-R圖如下:
|
根據ER圖,創建數據庫表!!!
5.1 一對多實現 (單向)
需求:通過ID查詢一條學生表的記錄,同時查詢該學生的對應的成績的信息!
5.1.1 說明
如圖所示:一個學生可以有多條成績的記錄,一條成績的記錄只屬於一個學生,所以學生表與成績表的關系是一對多的關系。
|
所以,通過JPA配置一對多的關系,可以通過學生表對應的實體類對象同時獲得兩個表的數據。
5.1.2 配置步驟
5.1.2.1 第一步:創建項目
說明:復制入門示例的項目即可。
5.1.2.2 第二步:創建單表實體類
(1)創建Student類
@Entity @Table(name="tb_student") public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="stu_id") private Long stuId; @Column(name="stu_name") private String stuName; @Column(name="stu_age") private Integer stuAge; @Column(name="stu_password") private String stuPassword;
public Student() { super(); } //補全get、set方法 } |
(2)創建Score類
@Entity @Table(name="tb_score") public class Score{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="sco_id") private Long scoId; @Column(name="sco_subject") private String scoSubject; @Column(name="sco_score") private Float scoScore; @Column(name="stu_id") private Long stuId;
public Score() { super(); } // 補全get、set方法 } |
5.1.2.3 第三步:配置一對多關聯關系
說明:通過@OneToMany注解配置。
修改Student類,配置一對多關系。
/** * 單向一對對,應該有學生來維護關系 * * 一個學生對應多個成績,一對多關系 * 多個成績我們使用list封裝起來 * * JPA 使用 @OneToMany 映射一對多 * fetch : 抓取策略 * FetchType.LAZY 懶加載,默認 (只有關聯對象在用到的時候才會去發送新的sql,默認關聯對象不會查詢) * 會多生成sql語句 :N+1 * FetchType.EAGER 迫切查詢 (多表連接查詢,只會發送一條sql語句) * @JoinColumn 設置兩張表之間外鍵列 */ @OneToMany(fetch=FetchType.EAGER) @JoinColumn(name="stu_id") private List<Score> scores; public void setScores(List<Score> scores) { this.scores = scores; } |
5.1.2.4 第四步:測試一對多查詢
@Test public void testOne2Many(){ //1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger();
Student student = manager.find(Student.class, 1L); System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName());
List<Score> scores = student.getScores(); for (Score score : scores) { System.out.println("科目:"+score.getScoSubject()+",分數:"+score.getScoScore()); }
//6、關閉資源 manager.close(); } |
查詢結果:
|
一對多關聯查詢成功!!!
5.2 多對一實現 (單向)
5.2.1 說明
需求:通過ID查詢一條成績表的記錄,同時查詢該成績的對應的學生的信息!
如圖所示:成績表里面,每一條記錄只能對應一個學生,但是學生編號不是唯一的。所以成績表里面的多條數據可以對應一個學生,所以我們稱多對一的關系。
|
5.2.2 配置步驟
5.2.2.1 第一步:創建項目
復制一對多示例項目即可。
5.2.2.2 第二步:創建單表實體類
修改Student類,去掉一對多配置即可。
5.2.2.3 第三步:配置多對一關聯關系
修改Score類,配置多對一關系
@Entity @Table(name="tb_score") public class Score{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="sco_id") private Long scoId;
@Column(name="sco_subject") private String scoSubject;
@Column(name="sco_score") private Float scoScore;
/** * jpa的多對一,關聯關系中指定的外鍵 和 關聯表的屬性有沖突 * 解決的方案:去掉關聯表中外鍵對應的屬性
/*@Column(name="stu_id") private Long stuId;
public Long getStuId() { return stuId; }
public void setStuId(Long stuId) { this.stuId = stuId; } */
/** * 1、分數和學生信息是多對一的關系 * 2、只需要一個學生的實體來引用學生的信息 */ @ManyToOne @JoinColumn(name="stu_id") private Student student;
public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } //補全get、set方法 } |
5.2.2.4 第四步:測試
@Test public void testMany2One(){ //1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger();
Score score = manager.find(Score.class, 1L); System.out.println("科目:"+score.getScoSubject()+",分數:"+score.getScoScore());
Student student = score.getStudent(); System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName()); //6、關閉資源 manager.close(); } |
查詢結果:
|
多對一配置成功!!!
5.3 雙向一對多|多對一(了解)
5.3.1 說明
(1)查詢學生信息,同時查詢成績信息。
(2)查詢成績信息,同時也可以查詢學生信息。
5.3.2 配置步驟
在同一個項目中,在Student類和Score類中,同時配置關聯關系。
(1)在Student類中配置一對多
@OneToMany //聲明是一對多的關系 @JoinColumn(name="stu_id") //指定關聯表中 外鍵的字段 private List<Score> scores;
public List<Score> getScores() { return scores; }
public void setScores(List<Score> scores) { this.scores = scores; } |
(2)在Score類中配置多對一
/** * jpa的多對一,關聯關系中指定的外鍵 和 關聯表的屬性有沖突 * 解決的方案:去掉關聯表中外鍵對應的屬性
@Column(name="stu_id") private Long stuId;
public Long getStuId() { return stuId; }
public void setStuId(Long stuId) { this.stuId = stuId; } */
/** * 1、分數和學生信息是多對一的關系 * 2、只需要一個學生的實體來引用學生的信息 */ @ManyToOne @JoinColumn(name="stu_id") private Student student;
public Student getStudent() { return student; }
public void setStudent(Student student) { this.student = student; } |
5.4 一對一實現
5.4.1 說明
需求:通過ID查詢學生的信息,通過也獲得學生對應的學生身份信息。
|
5.4.2 配置步驟
5.4.2.1 第一步:創建項目
復制一對多的示例項目即可。
5.4.2.2 第二步:創建單表實體類
(1)創建Student類
(2)創建Identity類
package cn.zj.jpa.entity;
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table;
@Entity @Table(name="tb_identity") public class Identity {
@Id /*由於一對一,外鍵表的主鍵字段值來自於主鍵表,所以只能手工輸入 手工輸入ID值,可以不指定主鍵生成策略 */ // @GeneratedValue @Column(name="stu_id") private Long stuId;
@Column(name="stu_identity") private String stuIdentity;
@Column(name="stu_no") private String stuNo; @OneToOne //2.必須要指定關聯的外鍵 @JoinColumn(name="stu_id") private Student student; public Identity() { super(); } // 補全get、set方法 } |
5.4.2.3 第三步:配置一對一關聯關系
說明:一對一關聯關系,也是支持雙向配置的。
可以在Student類、Identity類中同時配置關聯關系。
(1)修改Student類,配置一對一關系。
//學生表與學生身份表是一對一的關系,意味着,一個學生只能對應一條學生身份信息 //所以使用引用 //1.聲明關系,一對一 @OneToOne //2.必須要指定關聯的外鍵 @JoinColumn(name="stu_id") private Identity identity;
public Identity getIdentity() { return identity; } public void setiIdentity(Identity identity) { this.identity = identity; } |
(2)修改Score類
//1.聲明關系,一對一 @OneToOne //2.指定關聯的外鍵 @JoinColumn(name="stu_id") private Student student; public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } |
5.4.2.4 第四步:測試
說明:可以分別測試方向一對一關系。
@Test public void testOne2One1(){ //1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger();
Student student = manager.find(Student.class, 1L); System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName()); Identity identity = student.getIdentity(); System.out.println("學生學號:"+identity.getStuNo()+",身份證號:"+identity.getStuIdentity());
//6、關閉資源 manager.close(); }
@Test public void testOne2One2(){ //1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger(); Identity identity = manager.find(Identity.class, 1L); System.out.println("學生學號:"+identity.getStuNo()+",身份證號:"+identity.getStuIdentity()); Student student = identity.getStudent(); System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName()); //6、關閉資源 manager.close(); } |
(1)測試學生關聯身份信息
測試結果:
|
(2)測試身份信息關聯學生。
|
一對一配置成功!!!
5.5 配置多對多
5.5.1 說明
需求:
(1)通過ID查詢學生的信息,通過該學生信息也獲得對應的教師信息。
(2)通過ID查詢教師的信息,通過教師信息也獲得該對應的學生信息。
如圖所示:一個學生可以有多個教師,一個教師也可以有多個學生,所以學生和教師的關系是多對多的關系。
|
如上圖所示:
如果要從學生表的信息獲得教師表的信息。必須需要三個條件
1. 必須需要有一個中間表
2. 必須需要中間表對應本表的外鍵
3. 必須需要中間表對應關聯表的外鍵
5.5.2 配置步驟
5.5.2.1 第一步:創建項目
復制一個示例項目即可。
5.5.2.2 第二步:創建單表實體類
學生實體類Student
//1.指定實體類與表名的關系 //@Entity注解,指定該實體類是一個基於JPA規范的實體類 @Entity //@Table注解,指定當前實體類關聯的表 @Table(name="tb_student") public class Student { //@Id注解:聲明屬性為一個OID屬性 @Id //@GeneratedValue注解,指定主鍵生成策略 @GeneratedValue(strategy=GenerationType.IDENTITY) //@Column注解,設置屬性與數據庫字段的關系,如果屬性名和表的字段名相同,可以不設置 @Column(name="stu_id") private Long stuId;//BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '學生編號', @Column(name="stu_name") private String stuName;//VARCHAR(50) NULL DEFAULT NULL COMMENT '學生名字', @Column(name="stu_age") private Integer stuAge;//INT(11) NULL DEFAULT NULL COMMENT '學生年齡', @Column(name="stu_password") private String stuPassword;//VARCHAR(50) NULL DEFAULT NULL COMMENT '登錄密碼',
public Student() { super(); } //補全get、set方法 } |
教師實體類Teacher
@Entity @Table(name="tb_teacher") public class Teacher {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="tea_id") private Long teaId;
@Column(name="tea_name") private String teaName;
@Column(name="tea_password") private String teaPassword;
public Teacher() { super(); } //補全get、set方法 } |
5.5.2.3 第三步:配置多對多關系
(1)學生關聯教師,修改Student類
// 學生表和教師表是多對多的關系 // 所以,一個學生可以有多個教師,所以需要使用集合來存儲教師信息 //1.聲明關系,多對多 @ManyToMany //2.設置關聯的條件 //JoinTable用於對應中間表的設置 joinColumns設置中間表與本表關聯的外鍵 inverseJoinColumns設置中間表與關聯表對應的外鍵 @JoinTable(name="tb_stu_tea" ,joinColumns=@JoinColumn(name="stu_id"),inverseJoinColumns=@JoinColumn(name="tea_id")) private List<Teacher> teachers;
public List<Teacher> getTeachers() { return teachers; }
public void setTeachers(List<Teacher> teachers) { this.teachers = teachers; } |
(2)教師關聯學生,修改Teacher類
//因為教師與學生是多對多的關系,所以一個教師也可以有多個學生,需要使用集合來存儲學生的數據 //1.聲明教師和學生的關系,多對多 @ManyToMany //2.設置關聯的條件 @JoinTable(name="tb_stu_tea" ,joinColumns=@JoinColumn(name="tea_id"),inverseJoinColumns=@JoinColumn(name="stu_id")) private List<Student> students;
public List<Student> getStudents() { return students; }
public void setStudents(List<Student> students) { this.students = students; } |
5.5.2.4 測試
5.5.2.4.1 Step1:測試學生關聯教師
測試代碼
@Test public void testMany2Many1(){
//1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger();
Student student = manager.find(Student.class, 1L); System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName());
List<Teacher> teachers = student.getTeachers(); for (Teacher teacher : teachers) { System.out.println("教師id:"+teacher.getTeaId()+",教師姓名:"+teacher.getTeaName()); } //2、關閉資源 manager.close(); } |
測試結果:
|
5.5.2.4.2 Step2:測試教師關聯學生
測試代碼
@Test public void testMany2Many2(){
//1.獲得實體管理類 EntityManager manager = JPAUtils.getEntityManger();
Teacher teacher = manager.find(Teacher.class, 1L); System.out.println("教師id:"+teacher.getTeaId()+",教師姓名:"+teacher.getTeaName());
List<Student> students = teacher.getStudents(); for (Student student : students) { System.out.println("學生id:"+student.getStuId()+",學生姓名:"+student.getStuName()); } //2、關閉資源 manager.close(); } |
測試結果:
|
多對多配置成功!!!