java 实体类 临时注解_JPA:Java持久层API--配置流程
一、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實現框架二、 入門示例
任何框架的學習,都建議從配置流程圖開始。所以我們來一起理解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="Java Persistence API: XML Schemas" 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="Java Persistence API: XML Schemas" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="Java Persistence API: XML Schemas 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 {@Testpublic 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的差異。那么,編寫的代碼就可以一套代碼兼容多種數據庫!!!!三、JPA實現CRUD
修改StudentDAOTest類,測試crud操作
//通過OID刪除@Testpublic 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();}//更新@Testpublic void merge(){//1.獲得實體管理類對象EntityManager entityManager = JPAUtils.getEntityManger();//2.打開事務EntityTransaction transaction = entityManager.getTransaction();//3.啟動事務transaction.begin();//4.創建數據Student s=new Student();s.setStuName("李四");//更新必須要有一個OIDs.setStuId(3L);//5.更新entityManager.merge(s);//6。提交transaction.commit();//7.關閉entityManager.close();}//通過OID獲得數據@Testpublic void find(){//1.獲得實體管理類對象EntityManager entityManager = JPAUtils.getEntityManger();//通過OID查詢數據Student student = entityManager.find(Student.class, 1L);System.out.println(student.getStuName());entityManager.close();}//通過OID獲得數據@Testpublic void getReference(){//1.獲得實體管理類對象EntityManager entityManager = JPAUtils.getEntityManger();/*** getReference()和find()方法的區別:* getReference基于懶加載機制,即需要使用對象的時候,才執行查詢。*/Student student = entityManager.getReference(Student.class, 1L);System.out.println(student.getStuName());entityManager.close();}四、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查詢接口五、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 第四步:測試
@Testpublic 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;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 第四步:測試
說明:可以分別測試方向一對一關系。
@Testpublic 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(); }@Testpublic 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:測試學生關聯教師
測試代碼
@Testpublic 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:測試教師關聯學生
測試代碼
@Testpublic 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(); }測試結果:
多對多配置成功!!!
六、JPA逆向工程
6.1 說明
所謂的逆向工程就是通過數據庫的結構生成代碼。
目的:提高開發的效率
6.2 步驟
6.2.1 第一步:創建JPA項目
(1)創建項目
(2)指定項目名、JPA版本
(3)完成創建
6.2.2 第二步:生成JPA代碼
右擊項目的src文件夾,選擇new --> Other.. -->JPA的JPA Entities from Tables
6.2.2.1 Step1:創建新的數據庫連接
(1)選擇新建數據庫連接
(2)指定數據庫類型
(3)新建數據庫驅動
(4)配置驅動信息
驅動版本號
加載驅動jar包
配置jdbc四要素
6.2.2.2 Step2:配置表與表直接的關聯關系
(1)配置表關聯關系
選擇表,全選即可。
配置Student、Score一對多
依次配置其它的關聯關系即可。
6.2.2.3 Step3:指定生成實體類的名稱及結構
(1)修改關聯對象的屬性名
指定實體類的生成屬性
指定實體類的類名
依次修改其它類的屬性即可。
6.2.2.4 Step4:生成代碼
6.2.3 第三步:導入所需jar依賴
說明:Maven項目是可以導入jar包到本地的。 方法:打開DOS窗口,進入項目的pom文件所在目錄,執行命令: mvn dependency:copy-dependencies 前提:已經配置了Maven環境變量。6.2.4 第四步:更新項目
七、JPQL語言
7.1 說明
JPQL : Java Persistence Query Language : java持久化查詢語言。 它的作用是通過類似SQL的語法去操作實體類的對象。 語法和SQL一樣的,SQL操作的數據表,JPQL操作的對象 作用:實現個性化的查詢需求7.2 示例代碼
package cn.zj.jpa; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Query; import javax.persistence.TypedQuery;import org.junit.Test;import cn.zj.jpa.entity.Student; import cn.zj.jpa.util.JPAUtils;public class StudentDAOTest {//1.查詢所有學生的信息 @Test public void findAll(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得JPQL查詢對象 //標準的JPQL是必須要使用select //select語法: select 別名 from 類名 別名 TypedQuery<Student> query = manager.createQuery("select s from Student s", Student.class); //返回多條查詢的數據,getResultList //TypedQuery解決了HIbernate返回有警告的問題 List<Student> students = query.getResultList(); for (Student student : students) { System.out.println("學生名:"+student.getStuName()); } manager.close(); } //2.條件查詢 //需求:查詢名字有張字的學生 //注意:JPQL的語法,使用?設置參數,必須要在?后面設置下標值,下標值不能為負數 @Test public void findByCondition(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得JPQL查詢對象 //標準的JPQL是必須要使用select TypedQuery<Student> query = manager.createQuery("select s from Student s where s.stuName like ?1", Student.class); //3.設置條件 query.setParameter(1, "%張%"); List<Student> students = query.getResultList(); for (Student student : students) { System.out.println("學生名:"+student.getStuName()); } manager.close(); } @Test public void findByCondition1(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得JPQL查詢對象 //標準的JPQL是必須要使用select TypedQuery<Student> query = manager.createQuery("select s from Student s where s.stuName like :stuName", Student.class); //3.設置條件 query.setParameter("stuName", "%張%"); List<Student> students = query.getResultList(); for (Student student : students) { System.out.println("學生名:"+student.getStuName()); } manager.close(); } //需求:返回學生表的記錄數 @Test public void count(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得JPQL查詢對象 //標準的JPQL是必須要使用select //JPQL中的count操作返回值是Long值,所以用Long類型接收 TypedQuery<Long> query = manager.createQuery("select count(s) from Student s", Long.class); //如果返回的是一個值的查詢,使用getSingleResult Long count = query.getSingleResult(); System.out.println(count); manager.close(); } //需求:第二頁,每頁三條@Test public void findByPage(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得JPQL查詢對象 //標準的JPQL是必須要使用select TypedQuery<Student> query = manager.createQuery("select s from Student s", Student.class); //設置分頁條件 //1.設置開始位置,下標從0開始,第四條數據的下標為3 query.setFirstResult(3); //2.設置每頁的記錄 query.setMaxResults(3); List<Student> students = query.getResultList(); for (Student student : students) { System.out.println("學生名:"+student.getStuName()); } manager.close(); } /** 命名查詢語句的調用 * * 所謂的命名查詢,就是在實體類對象使用一個名字聲明一條JPQL語句 * 這樣可以通過name值獲得Query的語句 * * 命名查詢,在類名上做如下聲明:@NamedQuery(name="Student.findAll", query="SELECT s FROM Student s") public class Student { */@Test public void findAllByNamedQuery(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); //2.獲得一個查詢命名查詢語句的對象 //可以通過該對象調用實體類聲明的命名查詢語句 TypedQuery<Student> query = manager.createNamedQuery("Student.findAll", Student.class); List<Student> students = query.getResultList(); for (Student student : students) { System.out.println(student.getStuName()); } manager.close(); } //需求:通過JQOL刪除有張字的學生 @Test public void removeByCondition(){ //1獲得操作對象 EntityManager manager = JPAUtils.getEntityManager(); EntityTransaction transaction = manager.getTransaction(); transaction.begin(); try { //2.獲得JPQL查詢對象 //注意,調用操作的JPQL是不需要指定返回的類型 Query query = manager.createQuery("delete from Student s where s.stuName like ?1"); //參數對應?設置的下標值 query.setParameter(1, "%張%"); int count = query.executeUpdate(); System.out.println(count); transaction.commit(); manager.close(); } catch (Exception e) { transaction.rollback(); e.printStackTrace(); } } }7.3 JPQL補充:N+1問題
在一對多或者多對多查詢過程中,首先查詢1這一方的數據,然后根據1這一份的數據,查詢多的一方的數據。 當學生有N個的時候,總共查詢次數N+1次。 這個就稱之為N+1問題 當我們數據庫的量不大的時候,N+1問題基本沒有什么影響。如果當數據量很大的時候,查詢數據庫的次數,就很大了,這個就會影響數據庫的性能。如何解決這個問題?
可以通過JPQL來解決。
@Testpublic void one2manybyOne(){//1、獲取實體操作對象EntityManager manager = JPAUtils.getEntityManager();//JPQL是通過fetch這個關鍵詞,在查詢學生的信息的時候,一起將分數也查詢出來//最終執行的sql就只有一條TypedQuery<Student> query = manager.createQuery("select distinct s from Student s inner join fetch s.scores", Student.class);List<Student> students = query.getResultList();for (Student student : students) {System.out.println("學生姓名:"+student.getStuName()+",學生id:"+student.getStuId());List<Score> scores = student.getScores();for (Score score : scores) {System.out.println("科目:"+score.getScoSubject()+",分數:"+score.getScoScore());}System.out.println("---------------------------------");}}執行結果:
執行過程中,確實一條sql語句!!!
解決了頻繁查詢數據庫,帶來的數據庫性能損耗。
總結
以上是生活随笔為你收集整理的java 实体类 临时注解_JPA:Java持久层API--配置流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 建设银行怎么查卡号 怎么查看中国建设银行
- 下一篇: 线程与进程的区别_Java线程和PC进程