1. 程式人生 > >22-Java-Hibernate框架(二)

22-Java-Hibernate框架(二)

Hibernate的瞭解、Hibernate的搭建、Hibernate的基本使用流程等內容請閱讀21-Java-Hibernate(一)

五、Hibernate的Query查詢介面(重中之重)

  1.HQL語言瞭解:Hibernate Query Language(HQL),是hibernate的查詢語言,和SQL語句結構一樣,不同點注意點如下:

      (1)HQL是面向物件查詢,SQL是面向結構查詢

      (2)在HQL使用類名和屬性名,替代了原有的表名和欄位名  

      (3)在HQL語句中型別名和屬性名大小寫敏感  

      (4)如果需要select * 查詢所有欄位的值,在HQL語句中可以省略select *語句。例如:from User;

      (5)如果需要join...on表連線,需要建立關聯對映關係使用,不支援on子句

      (6)不要使用資料庫提供的字串函式、日期函式和一些特有的函式。一些基礎的函式可以使用,例如:max(),min(),sum(),avg(),count()等。

      (7)若只查詢字型類中某幾個欄位,返回的結果是泛型,值的集合

  2.具體Query常用的相關介面看程式碼演示

 1 package com.hibernatetest.test;
 2 
 3 import java.util.List;
 4 
 5 import org.hibernate.Query;
 6 import org.hibernate.Session;
 7 import com.hibernatetest.entity.User;
 8 import HibernatenateUtils.hibernateUtils;
 9 /*
10  * Query介面的常用方法:
11  *             1.setXXX():用於設定HQL語句中問號或變數的值
12  *             2.uniqueResult():得到單個物件(返回Object型別),在已知查詢結果中只有一個或零個才能用此函式,若有多個滿足條件的結果則報異常
13  *             3.executeUpdate():執行更新和刪除語句(返回int型作為操作成功的次數)
14  *             4.分頁查詢
15  *             5.list():獲取結果集(返回List型別)
16  *             6.iterate():獲取結果集(返回Iterator型別)
17  * */
18 public class QueryTest {
19     public static void main(String[] args) {
20         //第一步:Query物件是通過Session獲取的,所以先要通過之前寫hibernate工具類獲取Session物件
21         Session    session = hibernateUtils.getSession();
22         
23         //第二步:CreateQuery("HQL語句"):用於建立Query物件。
24         Query query = session.createQuery("from User where uname='zhangsan'");
25         
26         /*查詢引數設值setXXX(): (兩種方式)
27          * 1.問號設值
28          *             Query query = session.createQuery("from User where uid between ? and ?");
29          *             query.setInteger(0,5);//給第一個問號處賦值5
30          *             query.setInteger(1,10);//給第一個問號處賦值10
31          *             
32          * 2.變數設值
33          *             Query query = session.createQuery("from User where uname=:name");
34          *             query.setString(name,"zhangsan");//給name變數賦值
35          * 
36          * 3.模糊查詢
37          *             Query query = session.createQuery("from User where uname likt %?%");錯!!!!!
38          *             Query query = session.createQuery("from User where uname like ?");對!!!!
39          *             query.setString(0,"%" +"zhang"+ "%");//給name變數賦值
40          * 
41          * 4.分頁查詢
42          *             Query query = session.createQuery("from User where uname='zhangsan'");
43          *             query.setFirstResult(0);從滿足條件的資料中的第一條資料開始抓取
44          *             query.setMaxResult(2);從滿足條件的資料中只抓取前兩條資料
45          * 
46          * 5.獲取單個物件
47          *             Query query = session.createQuery("select count(*) from User where uname='zhangsan'");
48          *             Object object = query.uniqueResult();
49          * 
50          * 6.構造查詢
51          *             Query query = session.createQuery("select new User(5,"zhangsan") from User where uname='zhangsan'");
52          *             Object object = query.uniqueResult();
53          * */
54         
55         /*資料庫更新和刪除操作executeUpdate()
56          * 1.刪除
57          *             Query query = session.createQuery("delete from User where uid in(1,6)");//刪除id為1和6的資料,即使資料庫中沒有符合條件的資料也不會報錯
58          *             int execute = query.executeUpdate();//返回成功操作的次數
59          * */
60         
61         //第三步:Query獲取結果集
62         //1.list()獲取
63         List<?> list = query.list();
64         for(Object u:list){
65             User user = (User)u;
66             System.out.println(user);
67         }
68         /*2.iterate()獲取
69          * Iterator<?> iterator = query.iterate();
70          * while(iterator.hasNext()){
71          *        User user = (User)iterator.next();
72          *        System.out.println(user);
73          * }
74          * */
75         /*面試要考:list()和iterate()獲取結果集的區別:
76          * list():一次把所有資料從資料庫中取出來
77          * iterate():先從資料庫中查詢滿足條件的id,如果快取中包含全部要查詢的id的資料,就無需再查資料庫,直接從快取中取資料,否則,根據id從資料庫中取
78          * */
79         
80         //第四步:記得將Session關閉
81         session.close();
82     }
83 }

六、Hibernate的三個狀態

    物件(持久化類的例項)處於session物件的管理中才能與資料庫發生聯絡。在Hibernate框架應用中,我們依據物件物件與session物件的關係不同情況,

  把物件的狀態分為人的三種:瞬時狀態、遊離狀態、持久狀態。

    Transient(瞬時狀態|臨時狀態):在new之後,save()之前,資料庫沒有應用的資料

      如果物件未與session物件關聯過,我們稱該物件處於瞬時狀態

    Persistent(持久狀態):在save()之後,在session關閉之前,資料庫有相對應的資料

      如果物件與session關聯起來了,且該物件對應到資料庫記錄,則稱該物件處於持久狀態

    

  三狀態結構圖:

          

  三狀態轉換關係:

      1.瞬時狀態轉換為持久狀態:

          使用session的save()或saveOrUpdate()方法儲存物件後,該物件的狀態由瞬時狀態轉換為持久狀態

          使用session的get()或load()方法獲取物件後,該物件的狀態為持久狀態

      2.持久狀態轉換為瞬時狀態

          執行session物件的delete()方法後,物件由原來的持久狀態變為瞬時狀態,因此該物件沒有與任何的資料庫資料有關聯

      3.持久狀態變為遊離狀態

          執行session物件的evict()、clear()、close()方法,物件由原來的持久狀態變為遊離狀態。

      4.遊離狀態變為持久狀態

          重新獲取物件session物件,執行session物件的update()或saveOrUpdate方法,由遊離狀態轉換為持久狀態,該物件再次與session關聯

      5.遊離狀態轉換為瞬時狀態

          執行session的delete()方法,物件有遊離狀態變為瞬時狀態

          對瞬時狀態或遊離狀態的物件不再被其他物件引用時,會被Java虛擬機器按照垃圾回收機制處理

七、Hibernate根據實體自動構建生成表

  第一步:在hibernate.cfg.xml中新增<property name="hibernate.hbm2ddl.auto">update</property>,設定自動生成表

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8 <session-factory>
 9     <!--hibernate 方言 區分身份 -->
10     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
11     <!-- 資料庫連線資訊 -->
12     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13     <property name="connection.url">jdbc:mysql://127.0.0.1:3306/hibernatetest</property>
14     <property name="connection.username">root</property>
15     <property name="connection.password">root</property>
16 
17     <!-- hibernate自動生成表 update:如果資料庫不存在這張表自動建立一張表,如果存在不建立-->
18     <property name="hibernate.hbm2ddl.auto">update</property>
19     <!-- hibernate在控制檯顯示SQL語句 -->
20     <property name="show_sql">true</property>
21     <!-- hibernate格式化SQL,控制檯看起來更整齊 -->
22     <property name="format_sql">true</property>
23     <!-- 設定自動提交 -->
24     <property name="connection.autocommit">true</property>
25 
26     <!-- <property name="connection.characterEncoding">UTF-8</property> -->
27     <!--載入hibernate對映  -->
28     <mapping resource="com/hibernatetest/entity/Entity.hbm.xml" />
29 </session-factory>
30 
31 </hibernate-configuration>

  第二步:編寫實體類

  第三步:配置對映檔案

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:對應的實體類的許可權定名稱,table:對應資料庫表名稱 -->
 6  <class name="com.hibernatetest.entity.Entity" table="hibernateEntity">
 7      <!-- id標籤用於配置主鍵屬性
 8              name屬性:對應實體類中屬性名稱
 9              type屬性:可以省略,如果省略預設實體類中屬性的對應型別
10       -->
11   <id name="userid" type="java.lang.Integer">
12           <!-- column用於設定對應資料庫表中欄位名。不寫column標籤,資料庫中的欄位名則和Entity類中的屬性名一致
13               name:資料庫表中的欄位名
14               length:設定欄位長度
15            -->
16           <column name="userid"></column>
17           <!-- generator用於設定主鍵生成策略
18                native:資料庫本地生成策略,適用於多個數據庫
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql資料庫使用,適用於所有資料庫,先查詢出最大的id,在此基礎上+1,有可能出現併發的問題
21                uuid:生成32位,不會重複的主鍵,可以達到真正的跨資料庫
22                foreign:通常在一對一關聯的時候使用
23                自增長:identity,適用於mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property標籤用於配置其他屬性
29              name:對應實體類中屬性名稱
30              type:可以省略,如果省略預設實體類中屬性的對應型別
31       -->
32   <property name="username" type="java.lang.String">
33            <column name="username" length="32"></column>
34   </property>
35   <property name="password" type="java.lang.String" >
36            <column name="password" length="32"></column>
37   </property>
38   
39  </class>
40  
41 </hibernate-mapping>

  第四步:編寫測試類測試

    控制檯顯示hibernate在資料庫沒找到hibernateEntity表

          

    於是它便會在資料庫自動生成一張表

          

八、Hibernate的關聯對映

     實體與實體之間有一對一、多對一、多對多的關係,Hibernate也因此需要對錶與表之間進行關聯對映配置。

     假設:有一張表為Entity,表中有userid,username,password三個欄位,另一張表Grade,表中有gradeid,userid,grade。

     我現在通過userid查詢對應另一張表中的grade(此處可以理解為多對一)。步驟如下:

      第一步:搭建Hibernate,配置hibernate.cfg.xml,此處由於我們有兩張表,所以需要載入兩個對映檔案

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8 <session-factory>
 9     <!--hibernate 方言 區分身份 -->
10     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
11     <!-- 資料庫連線資訊 -->
12     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13     <property name="connection.url">jdbc:mysql://127.0.0.1:3306/hibernatetest</property>
14     <property name="connection.username">root</property>
15     <property name="connection.password">root</property>
16 
17     <!-- hibernate自動生成表 update:如果資料庫不存在這張表自動建立一張表,如果存在不建立-->
18     <property name="hibernate.hbm2ddl.auto">update</property>
19     <!-- hibernate在控制檯顯示SQL語句 -->
20     <property name="show_sql">true</property>
21     <!-- hibernate格式化SQL,控制檯看起來更整齊 -->
22     <property name="format_sql">true</property>
23     <!-- 設定自動提交 -->
24     <property name="connection.autocommit">true</property>
25 
26     <!-- <property name="connection.characterEncoding">UTF-8</property> -->
27     
28     <!--載入hibernate對映檔案  -->
29     <mapping resource="com/hibernatetest/entity/Entity.hbm.xml" />
30     <mapping resource="com/hibernate/grade/Grade.hbm.xml" />
31 </session-factory>
32 
33 </hibernate-configuration>

     第二步:配置兩張表對應的對映檔案

Entity.hbm.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:對應的實體類的許可權定名稱,table:對應資料庫表名稱 -->
 6  <class name="com.hibernatetest.entity.Entity" table="hibernateEntity">
 7      <!-- id標籤用於配置主鍵屬性
 8              name屬性:對應實體類中屬性名稱
 9              type屬性:可以省略,如果省略預設實體類中屬性的對應型別
10       -->
11   <id name="userid" type="java.lang.Integer">
12           <!-- column用於設定對應資料庫表中欄位名。不寫column標籤,資料庫中的欄位名則和Entity類中的屬性名一致
13               name:資料庫表中的欄位名
14               length:設定欄位長度
15            -->
16           <column name="userid"></column>
17           <!-- generator用於設定主鍵生成策略
18                native:資料庫本地生成策略,適用於多個數據庫
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql資料庫使用,適用於所有資料庫,先查詢出最大的id,在此基礎上+1,有可能出現併發的問題
21                uuid:生成32位,不會重複的主鍵,可以達到真正的跨資料庫
22                foreign:通常在一對一關聯的時候使用
23                自增長:identity,適用於mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property標籤用於配置其他屬性
29              name:對應實體類中屬性名稱
30              type:可以省略,如果省略預設實體類中屬性的對應型別
31       -->
32   <property name="username" type="java.lang.String">
33            <column name="username" length="32"></column>
34   </property>
35   <property name="password" type="java.lang.String" >
36            <column name="password" length="32"></column>
37   </property>
38  </class>
39  
40 </hibernate-mapping>

Grade.hbm.xml:(此處需要加入對grade表的多對一的對映關係)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:對應的實體類的許可權定名稱,table:對應資料庫表名稱 -->
 6  <class name="com.hibernate.grade.Grade" table="hibernateGrade">
 7      <!-- id標籤用於配置主鍵屬性
 8              name屬性:對應實體類中屬性名稱
 9              type屬性:可以省略,如果省略預設實體類中屬性的對應型別
10       -->
11   <id name="gradeid" type="java.lang.Integer">
12           <!-- column用於設定對應資料庫表中欄位名。不寫column標籤,資料庫中的欄位名則和Entity類中的屬性名一致
13               name:資料庫表中的欄位名
14               length:設定欄位長度
15            -->
16           <column name="gradeid"></column>
17           <!-- generator用於設定主鍵生成策略
18                native:資料庫本地生成策略,適用於多個數據庫
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql資料庫使用,適用於所有資料庫,先查詢出最大的id,在此基礎上+1,有可能出現併發的問題
21                uuid:生成32位,不會重複的主鍵,可以達到真正的跨資料庫
22                foreign:通常在一對一關聯的時候使用
23                自增長:identity,適用於mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property標籤用於配置其他屬性
29              name:對應實體類中屬性名稱
30              type:可以省略,如果省略預設實體類中屬性的對應型別
31       -->
32       
33   <!-- 多對一對映關係 -->
34   <!-- name:當前Grade類的Entity屬性
35          column:Grade類的外來鍵
36          fetch:有join和select.預設為select
37                   select:查了當前表之後,再查外來鍵所在的那張表
38                   join:在多對一將原本需要兩條sql語句以left outer join(左外連線)方式用一條語句解決
39          cascade:級聯操作關聯表:慎用
40                  save-update:在新增或操作的時候使用級聯操作關聯表
41                  delete:在刪除的時候使用級聯操作關聯表
42                  all:在所有操作的時候使用級聯操作關聯表
43                  none:任何時候都不使用
44    -->
45   <many-to-one name="entity" column="userid" fetch="join"></many-to-one>
46   
47   <property name="grade" type="java.lang.Double" >
48            <column name="grade"></column>
49   </property>
50  </class>
51  
52 </hibernate-mapping>

      第三步:編寫兩張表對應的實體類

Entity類:

 1 package com.hibernatetest.entity;
 2 
 3 public class Entity {
 4     private Integer userid;
 5     private String username;
 6     private String password;
 7     public Entity() {
 8         super();
 9         // TODO Auto-generated constructor stub
10     }
11     public Entity(Integer userid, String username, String password) {
12         super();
13         this.userid = userid;
14         this.username = username;
15         this.password = password;
16     }
17     public Integer getUserid() {
18         return userid;
19     }
20     public void setUserid(Integer userid) {
21         this.userid = userid;
22     }
23     public String getUsername() {
24         return username;
25     }
26     public void setUsername(String username) {
27         this.username = username;
28     }
29     public String getPassword() {
30         return password;
31     }
32     public void setPassword(String password) {
33         this.password = password;
34     }
35     @Override
36     public int hashCode() {
37         final int prime = 31;
38         int result = 1;
39         result = prime * result
40                 + ((password == null) ? 0 : password.hashCode());
41         result = prime * result + ((userid == null) ? 0 : userid.hashCode());
42         result = prime * result
43                 + ((username == null) ? 0 : username.hashCode());
44         return result;
45     }
46     @Override
47     public boolean equals(Object obj) {
48         if (this == obj)
49             return true;
50         if (obj == null)
51             return false;
52         if (getClass() != obj.getClass())
53             return false;
54         Entity other = (Entity) obj;
55         if (password == null) {
56             if (other.password != null)
57                 return false;
58         } else if (!password.equals(other.password))
59             return false;
60         if (userid == null) {
61             if (other.userid != null)
62                 return false;
63         } else if (!userid.equals(other.userid))
64             return false;
65         if (username == null) {
66             if (other.username != null)
67                 return false;
68         } else if (!username.equals(other.username))
69             return false;
70         return true;
71     }
72     @Override
73     public String toString() {
74         return "Entity [userid=" + userid + ", username=" + username
75                 + ", password=" + password + "]";
76     }
77     
78 }

Grade類:

 1 package com.hibernate.grade;
 2 
 3 import com.hibernatetest.entity.Entity;
 4 
 5 public class Grade {
 6     private Integer gradeid;
 7     private Entity entity;
 8     private Double grade;
 9     public Grade() {
10         super();
11         // TODO Auto-generated constructor stub
12     }
13     public Grade(Integer gradeid, Entity entity, Double grade) {
14         super();
15         this.gradeid = gradeid;
16         this.entity = entity;
17         this.grade = grade;
18     }
19     public Integer getGradeid() {
20         return gradeid;
21     }
22     public void setGradeid(Integer gradeid) {
23         this.gradeid = gradeid;
24     }
25     public Entity getEntity() {
26         return entity;
27     }
28     public void setEntity(Entity entity) {
29         this.entity = entity;
30     }
31     public Double getGrade() {
32         return grade;
33     }
34     public void setGrade(Double grade) {
35         this.grade = grade;
36     }
37     @Override
38     public int hashCode() {
39         final int prime = 31;
40         int result = 1;
41         result = prime * result + ((entity == null) ? 0 : entity.hashCode());
42         result = prime * result + ((grade == null) ? 0 : grade.hashCode());
43         result = prime * result + ((gradeid == null) ? 0 : gradeid.hashCode());
44         return result;
45     }
46     @Override
47     public boolean equals(Object obj) {
48         if (this == obj)
49             return true;
50         if (obj == null)
51             return false;
52         if (getClass() != obj.getClass())
53             return false;
54         Grade other = (Grade) obj;
55         if (entity == null) {
56             if (other.entity != null)
57                 return false;
58         } else if (!entity.equals(other.entity))
59             return false;
60         if (grade == null) {
61             if (other.grade != null)
62                 return false;
63         } else if (!grade.equals(other.grade))
64             return false;
65         if (gradeid == null) {
66             if (other.gradeid != null)
67                 return false;
68         } else if (!gradeid.equals(other.gradeid))
69             return false;
70         return true;
71     }
72     @Override
73     public String toString() {
74         return "Grade [gradeid=" + gradeid + ", entity=" + entity + ", grade="
75                 + grade + "]";
76     }
77     
78 }

      第四步:編寫HibernateUtils工具類和測試類

測試類:

 1 package Hibernatetest; 4 
 5 import org.hibernate.Query;
 6 import org.hibernate.Session;
 7 import org.hibernate.Transaction;
 8 
 9 import com.hibernate.grade.Grade;
10 import com.hibernatetest.entity.Entity;
11 
12 import HibernatenateUtils.hibernateUtils;
13 
14 public class annotationtest {
15     
16     public void test(){
17         
18     }
19     public static void main(String[] args) {
20         Session session = hibernateUtils.getSession();
21         
22         //先製造兩條記錄在資料庫中
23         Transaction transaction = session.beginTransaction();
24         Entity user1 = new Entity(null,"zhangsan","1111");
25         Grade grade1 = new Grade(null,user1,Double.valueOf(85));
26         session.save(user1);
27         session.save(grade1);
28         transaction.commit();
29         
30         transaction = session.beginTransaction();
31         Entity user2 = new Entity(null,"lisi","2222");
32         Grade grade2 = new Grade(null,user2,Double.valueOf(100));
33         session.save(user2);
34         session.save(grade2);
35         transaction.commit();
36         
37         //查詢測試
38         Grade grade = session.get(Grade.class,3);
39         System.out.println(grade);
40         session.close();
41     }
42 }

執行結果:

    

&n