OK,之前主要是講解了一下關於前端的知識的,如果你們還沒看過的,可以先去看看前面的內容,因爲真正的是乾貨,都是自己在學習的過程中覺得還不錯的知識點就進行整理的。那麼,我將對J2EE企業級中的幾大框架進行知識點的講解。首先,這一篇接我將講解一下Hibernate框架的一些知識點,其餘的框架將在後續進行整理。
咳咳,來說一說JDBC的一些缺點,然後引出Hibernate的原因。
(1)JDBC缺點:
1、代碼比較繁瑣
2、sql語句平臺的移植性不是很強
3、沒有data pool(數據緩存)
4、當jdbc調用mysql的存儲過程的時候,存儲過程本身移植性比較差
5、沒有做到面向對象開發
(2)Hibernate優點:
1、面向對象的編程
2、緩存
重點
一級緩存 二級緩存 查詢緩存
如果數據量不是特別大
hibernate緩存
oscache 不支持分佈式緩存
ehcache 不支持分佈式緩存
redis 分佈式緩存
memorycache 分佈式緩存
3、代碼操作比較簡單
4、平臺的移植性比較強
(3)Hibernate缺點:
如果該項目對sql的優化要求特別高,不適合用hibernate
如果數據庫的數據量特別大,也不適合用hibernate
如果表與表之間的關係比較複雜,也不能用hibernate來做
首先講一下Hibernate框架搭建的步驟,然後再細細的對其中的內容進行講解:
(1)導包
(2)準備實體類(也就是一般中的JavaBean類) 以及 orm元數據
(3)創建主配置文件
1:Hibernate中的數據庫表與實體對象的映射配置詳解(ORM元數據)
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <!-- 配置表與實體對象的關係 -->
- <!-- package屬性:填寫一個包名.在元素內部凡是需要書寫完整類名的屬性,可以直接寫簡答類名了. -->
- <hibernate-mapping package="cn.itheima.domain" >
- <!--
- class元素: 配置實體與表的對應關係的
- name: 完整類名
- table:數據庫表名
- -->
- <class name="Customer" table="cst_customer" >
- <!-- id元素:配置主鍵映射的屬性
- name: 填寫主鍵對應屬性名
- column(可選): 填寫表中的主鍵列名.默認值:列名會默認使用屬性名
- type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
- 每個類型有三種填法: java類型|hibernate類型|數據庫類型
- not-null(可選):配置該屬性(列)是否不能爲空. 默認值:false
- length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度
- -->
- <id name="cust_id" >
- <!-- generator:主鍵生成策略 -->
- <generator class="native"></generator>
- </id>
- <!-- property元素:除id之外的普通屬性映射
- name: 填寫屬性名
- column(可選): 填寫列名
- type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型.
- 每個類型有三種填法: java類型|hibernate類型|數據庫類型
- not-null(可選):配置該屬性(列)是否不能爲空. 默認值:false
- length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度
- -->
- <property name="cust_name" column="cust_name" >
- <!-- <column name="cust_name" sql-type="varchar" ></column> -->
- </property>
- <property name="cust_source" column="cust_source" ></property>
- <property name="cust_industry" column="cust_industry" ></property>
- <property name="cust_level" column="cust_level" ></property>
- <property name="cust_linkman" column="cust_linkman" ></property>
- <property name="cust_phone" column="cust_phone" ></property>
- <property name="cust_mobile" column="cust_mobile" ></property>
- </class>
- </hibernate-mapping>
2:Hibernate主配置(位置:寫在src下面的一個xml文件,並且名字要爲hibernate.cfg.xml)
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
-
- <!--
- #hibernate.dialect org.hibernate.dialect.MySQLDialect
- #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
- #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
- #hibernate.connection.driver_class com.mysql.jdbc.Driver
- #hibernate.connection.url jdbc:mysql:///test
- #hibernate.connection.username gavin
- #hibernate.connection.password
- -->
- <!-- 數據庫驅動 -->
- <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
- <!-- 數據庫url -->
- <property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
- <!-- 數據庫連接用戶名 -->
- <property name="hibernate.connection.username">root</property>
- <!-- 數據庫連接密碼 -->
- <property name="hibernate.connection.password">1234</property>
- <!-- 數據庫方言
- 不同的數據庫中,sql語法略有區別. 指定方言可以讓hibernate框架在生成sql語句時.針對數據庫的方言生成.
- sql99標準: DDL 定義語言 庫表的增刪改查
- DCL 控制語言 事務 權限
- DML 操縱語言 增刪改查
- 注意: MYSQL在選擇方言時,請選擇最短的方言.
- -->
- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
-
-
- <!-- #hibernate.show_sql true
- #hibernate.format_sql true
- -->
- <!-- 將hibernate生成的sql語句打印到控制檯 -->
- <property name="hibernate.show_sql">true</property>
- <!-- 將hibernate生成的sql語句格式化(語法縮進) -->
- <property name="hibernate.format_sql">true</property>
- <!--
- ## auto schema export 自動導出表結構. 自動建表
- #hibernate.hbm2ddl.auto create 自動建表.每次框架運行都會創建新的表.以前表將會被覆蓋,表數據會丟失.(開發環境中測試使用)
- #hibernate.hbm2ddl.auto create-drop 自動建表.每次框架運行結束都會將所有表刪除.(開發環境中測試使用)
- #hibernate.hbm2ddl.auto update(推薦使用) 自動生成表.如果已經存在不會再生成.如果表有變動.自動更新表(不會刪除任何數據).
- #hibernate.hbm2ddl.auto validate 校驗.不自動生成表.每次啓動會校驗數據庫中表是否正確.校驗失敗.
- -->
- <property name="hibernate.hbm2ddl.auto">update</property>
- <!-- 引入orm元數據
- 路徑書寫: 填寫src下的路徑
- -->
- <mapping resource="cn/itheima/domain/Customer.hbm.xml" />
-
- </session-factory>
- </hibernate-configuration>
3:Hibernate中的API的詳解(其中分幾個步驟來進行講解,方便大家進行閱讀和練習)
(1)Configuration對象
- public void fun1(){
- //1 創建,調用空參構造
- Configuration conf = new Configuration();
- //2 讀取指定主配置文件 => 空參加載方法,加載src下的hibernate.cfg.xml文件
- conf.configure();
- //3 讀取指定orm元數據(擴展),如果主配置中已經引入映射配置.不需要手動加載
- //conf.addResource(resourceName);
- //conf.addClass(persistentClass);
-
- //4 根據配置信息,創建 SessionFactory對象
- SessionFactory sf = conf.buildSessionFactory();
-
- }
(2)
SessionFactory對象
SessionFactory功能: 用於創建操作數據庫核心對象session對象的工廠.
簡單說功能就一個---創建session對象
注意:1.sessionfactory 負責保存和使用所有配置信息.消耗內存資源非常大.
2.sessionFactory屬於線程安全的對象設計.
3:sessionFactory是單例模式
4:sessionFatory封裝的信息全部都是公共的
結論: 保證在web項目中,只創建一個sessionFactory.
下面代碼就是兩種獲取Session對象的方法。區別兩個方法的不同點。
- //5 獲得session
- //打開一個新的session對象
- sf.openSession();
- //獲得一個與線程綁定的session對象
- sf.getCurrentSession();
稍微講解一下關於openSession()方法的細節內容:
該方法的缺點: 1、只要調用一次openSession方法都會打開一個新的連接
2、這種方式效率不是很高
3、利用這種方式很容器的就可以操作session的緩存
這裏重點分析一下關於第二種方法getCurrentSession()的詳細內容(非常重要,裏面用到的設計模式很經典):
從上面的簡化圖,應該就能明白具體改方法做了些什麼了,如果想了解更加詳細的執行過程,就可以根據該方法進入源碼進行閱讀了。
好了,這裏說一下,爲什麼要把Session對象放入到threadloacl對象中,有以下幾個好處:
1、把session放入到threadlocal中,確保線程安全
2、在整個線程中可以共享session,並且該session只有一個
3、在threadlocal中存放Map<SessionFactory,Session>,因爲整個hibernate應用sessionFactory只有一個,所以session肯定只有一個
咳咳,注意了,如果要用getCurrentSession()方法的話,可不是直接調用這個方法就可以了的,是需要進行下面的配置的,否則就會報錯報錯報錯!!!
第一步:在hibernate.cfg.xml文件中添加一個屬性配置
- <property name="current_session_context_class">thread</proerty>
第二步:在使用getCurrentSession()方法獲得的session對象之後,再進行crud操作的時候,必須必須必須打開事務,否則會報錯,無法進行操作。
------這個也不是很懂爲什麼hibernate框架在設計的時候出於什麼目的,因爲比如get()方法就不需要事務管理也沒關係呀。所以,這個是需要注意的一點。
第三步:在進行完crud操作的事務commit()操作之後,不需要手動再進行session對象的close()方法,這是會自動關閉的,如果手動關閉了,會報錯。-----------這個嘛,就把事務和session對象給綁定了,也有不好的地方,比如在事務提交之後,還想操作session的話,這樣就是不行的了。也正是這個原因,後面在Spring框架的時候,對這個設置可以進行了配置修改。
(3)Session對象(主要就是進行與數據庫之間的CRUD操作)
session對象功能: 表達hibernate框架與數據庫之間的連接(會話).session類似於JDBC年代的connection對象. 還可以完成對數據庫中數據的增刪改查操作。創建一個session相當於打開一個數據庫連接,關閉session就相當於關閉一個數據庫連接。
session是hibernate操作數據庫的核心對象
- //4 session獲得操作事務的Transaction對象
- //獲得操作事務的tx對象
- //Transaction tx = session.getTransaction();
- //開啓事務並獲得操作事務的tx對象(建議使用)
- Transaction tx2 = session.beginTransaction();
- //----------------------------------------------
- //----------------------------------------------
- tx2.commit();//提交事務
- tx2.rollback();//回滾事務
- session.close();//釋放資源
- sf.close();//釋放資源
1:添加數據
- public void fun2(){
- //1 創建,調用空參構造
- Configuration conf = new Configuration().configure();
- //2 根據配置信息,創建 SessionFactory對象
- SessionFactory sf = conf.buildSessionFactory();
- //3 獲得session
- Session session = sf.openSession();
- //4 session獲得操作事務的Transaction對象
- //獲得操作事務的tx對象
- //Transaction tx = session.getTransaction();
- //開啓事務並獲得操作事務的tx對象(建議使用)
- Transaction tx2 = session.beginTransaction();
- //----------------------------------------------
- Customer c = new Customer();
- c.setCust_name("我是第一個測試哦");
-
- session.save(c);
- //----------------------------------------------
- tx2.commit();//提交事務
- session.close();//釋放資源
- sf.close();//釋放資源
- }
2:查詢id=1的數據(注意一下:因爲id設置的是long型,所以在1後面有個L,表示的是long型的數據,下同)
- //----------------------------------------------
-
- Customer customer = session.get(Customer.class, 1l);
-
- System.out.println(customer);
- //----------------------------------------------
3:更新id=1的數據
- //----------------------------------------------
- //1 獲得要修改的對象
- Customer c = session.get(Customer.class, 1l);
- //2 修改
- c.setCust_name("哈哈");
- //3 執行update
- session.update(c);
- //----------------------------------------------
4:刪除id=1的數據
- //----------------------------------------------
- //1 獲得要修改的對象
- Customer c = session.get(Customer.class, 1l);
- //2 調用delete刪除對象
- session.delete(c);
- //----------------------------------------------
(4)Transaction對象(主要功能:打開事務,提交事務,回滾事務,這上面的session中已經進行了代碼的演示了,可以翻上去看看,比較簡單)
在Hibernate中,默認是關閉的,必須手動打開。(JDBC也是默認不打開的,所以纔會發生很多多線程處理的問題)
4:封裝獲取session對象的工具方法(這個在開發中是需要的,因爲都需要有工具類,這樣能夠優化程序)
- public class HibernateUtils {
- private static SessionFactory sf;
-
- static{
- //1 創建,調用空參構造
- Configuration conf = new Configuration().configure();
- //2 根據配置信息,創建 SessionFactory對象
- sf = conf.buildSessionFactory();
- }
-
- //獲得session => 獲得全新session
- public static Session openSession(){
- //3 獲得session
- Session session = sf.openSession();
-
- return session;
-
- }
- //獲得session => 獲得與線程綁定的session
- public static Session getCurrentSession(){
- //3 獲得session
- Session session = sf.getCurrentSession();
-
- return session;
- }
註解:由於sessionFactory對象消耗的資源很大,所以在項目中使得只存在一個即可,這樣的話,則可以把前面兩句代碼放到靜態代碼塊中(這就有個知識點了,爲什麼放在static中只會執行一次呢?其實很簡單,因爲靜態代碼塊只會在類加載中執行,jvm中存在有緩衝區,所以只會執行一次唄。)
5:Hibernate中的實體類的JavaBean的編寫規則
(1)持久化類提供無參數構造,(非常重要,必須有個無參構造,否則就會在Hibernate操作的時候出現問題)
(2)成員變量私有,提供公有的Get、Set方法,需提供屬性(注意一個JavaBean中什麼才叫做屬性?只有當是get、set方法得到的纔是叫屬性,比如private String name,這隻能叫做成員變量,而不是屬性,只有當有setName這個方法或者GetName這方法的時候,才能將這個稱作屬性,這可是面試常考的哦!!)
(3)持久化類中的屬性,應儘量使用包裝類型(包裝類型,可以防止由於讀取到數據庫中的null字段而引起的異常)
(4)持久化類需要提供oid,與數據庫中的主鍵對應(沒有主鍵的數據庫,是無法映射到Hibernate當中的)
(5)不要用final修飾class(因爲Hibernate是通過CGlib來實現的動態代理生成對象,代理對象是繼承被代理的對象)
6:主鍵類型
(1)自然主鍵(少見):數據庫中表的業務中,有某業務列符合主鍵的規範,則稱爲自然主鍵(比如人的身份證號,學號這些)
(2)代理主鍵(常見):數據庫中表中,沒有業務列符合主鍵的規範,則需要創建一個沒有意義的列,則稱爲代理主鍵(比如數據庫中的id這個列,一般都沒有實際意義。)
7:Hibernate中對主鍵生成策略(7種,主要就是在xml配置文件中進行控制)
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="cn.itheima.domain" >
- <class name="Customer" table="cst_customer" >
- <id name="cust_id" >
- <!-- generator:主鍵生成策略.就是每條記錄錄入時,主鍵的生成規則.(7個)
- identity : 主鍵自增.由數據庫來維護主鍵值.錄入時不需要指定主鍵.
- sequence: Oracle中的主鍵生成策略.
- increment(瞭解): 主鍵自增.由hibernate來維護.每次插入前會先查詢表中id最大值.+1作爲新主鍵值.
- hilo(瞭解): 高低位算法.主鍵自增.由hibernate來維護.開發時不使用.
- native:hilo+sequence+identity 自動三選一策略.
- uuid: 產生隨機字符串作爲主鍵. 主鍵類型必須爲string 類型.
- assigned:自然主鍵生成策略. hibernate不會管理主鍵值.由開發人員自己錄入.
-
- -->
- <generator class="increment"></generator>
- </id>
- <property name="cust_name" column="cust_name" ></property>
- <property name="cust_source" column="cust_source" ></property>
- <property name="cust_industry" column="cust_industry" ></property>
- <property name="cust_level" column="cust_level" ></property>
- <property name="cust_linkman" column="cust_linkman" ></property>
- <property name="cust_phone" column="cust_phone" ></property>
- <property name="cust_mobile" column="cust_mobile" ></property>
- </class>
- </hibernate-mapping>
8:Hibernate的對象狀態
(1)瞬時(臨時)狀態:沒有id,沒有與session關聯----------------------肯定是從new創建來的
(2)持久化狀態:有id,有與session關聯
(3)遊離|託管狀態:有id,沒有與session關聯-----------------------肯定是從持久化狀態轉換過來的
上面三種狀態的互相轉變:
瞬時----》持久化----------------------通過session中的save()方法
持久化---》遊離----------------------通過session中的close()/clear()/evcit()方法
遊離----》持久化------------------- 通過session中的update()方法
持久化---》瞬時---------------------通過session中的delete()方法
直接到持久化-----------------------通過session中的get()方法
文字變成圖就可以利用下面這個來看清楚一點了。
實例分析:用一個例子來說明上面理論的分析:
再說一個知識點,就是關於session的flush()方法的原理.。當執行session.flush方法的時候,hibernate內部會檢查所有的持久化對象會判斷該對象和數據庫有沒有對應的數據(根據標示符id),如果沒有則發出insert語句,如果有,則再讓該對象和副本進行對比,如果和副本一樣,則什麼都不做,如果不一樣,則發出update語句session.flush的時候,只不過是向數據庫發送了sql語句,但是值在數據庫中並不存在。
9:Hibernate的一級緩存
功能:提高效率
(1)提高查詢效率
(2)減少不必要的修改語句的發送(通過快照)
緩存的類型:
(1)對象緩存:把對象的標示符作爲key值,把對象本身作爲value值
(2)數據緩存:可以把sql語句作爲key值,把結果作爲value值
Hibernate的一級緩存的測試實例:
先寫一個獲取SessionFactory的工具類(主要是用於方便獲取Session對象)
- package com.itheima11.hibernate.utils;
-
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
-
- public class HibernateUtils {
- public static SessionFactory sessionFactory;
- static{
- Configuration configuration = new Configuration();
- configuration.configure();
- sessionFactory = configuration.buildSessionFactory();
- }
- }
測試代碼:
- public class SessionCacheTest extends HibernateUtils{
- @Test
- public void testGet(){
- Session session = sessionFactory.openSession();
- Person person = (Person)session.get(Person.class, 1L);//發出sql語句
- person = (Person)session.get(Person.class, 1L);//沒有發出sql語句 該對象來自於緩存
- session.close();
- }
-
- /**
- * 統計機制
- */
- @Test
- public void testStatistics(){
- Session session = sessionFactory.openSession();
- Person person = (Person)session.get(Person.class, 1L);//發出sql語句
- System.out.println(session.getStatistics().getEntityCount());//計算hibernate的一級緩存中的對象的個數
- session.close();
- }
- }
咳咳,好了,現在總結一下知識點(面試會問的哦),通過上面的例子,我們可以看到:
(1):執行session.get()方法的時候,會把對象放入到一級緩存中
(2):當session執行get(),save(),update(),list()方法的時候,都會把對象放入到一級緩存(如果想測試的話,也很簡單,類似那面的寫法進行不斷的輸入緩存裏面的對象個數的值就能夠明白了)
(3):當session執行evict(),close(),clear()方法的時候,都會清除一級緩存中的對象
(4):咱們再聯繫一下關於hibernate中對象的三種狀態,然後再結合這一級緩存知識,難道沒有發現什麼相關聯的東西嗎?
答案就是(敲黑板):其實只要對象是持久化狀態,那麼就在一級緩存中,這就是爲什麼第(2)點和第(3)點會有這樣的結論。所以,總結起來就是,判斷是否存在於一級緩存中,就看是否是執行了持久化狀態的操作,這樣就能夠把Hibernate的對象狀態和一級緩存技術知識連起來。是不是是不是一下就明白了兩個知識點,是否很開心呢?這個可是在面試的時候經常問到的問題哦。
10:hibernate中的批量查詢(概述)
(1)HQL語句:hibernate特有的語句(使用於多表但不復雜的查詢)
下面通過例子來進行說明不同情況的查詢方法(大家請仔細看,區別原生的SQL語句):
- //基本查詢
- public void fun1(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1> 書寫HQL語句
- // String hql = " from cn.itheima.domain.Customer "; //如果名字都沒有重複的,則可以利用下面的語句
- String hql = " from Customer "; // 查詢所有Customer對象
- //2> 根據HQL語句創建查詢對象
- Query query = session.createQuery(hql);
- //3> 根據查詢對象獲得查詢結果
- List<Customer> list = query.list(); // 返回list結果
- //query.uniqueResult();//接收唯一的查詢結果
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //條件查詢
- //HQL語句中,不可能出現任何數據庫相關的信息的
- public void fun2(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1> 書寫HQL語句
- String hql = " from Customer where cust_id = 1 "; // 查詢所有Customer對象
- //2> 根據HQL語句創建查詢對象
- Query query = session.createQuery(hql);
- //3> 根據查詢對象獲得查詢結果
- Customer c = (Customer) query.uniqueResult();
-
- System.out.println(c);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
-
- //條件查詢
- //問號佔位符
- public void fun3(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1> 書寫HQL語句
- String hql = " from Customer where cust_id = ? "; // 查詢所有Customer對象
- //2> 根據HQL語句創建查詢對象
- Query query = session.createQuery(hql);
- //設置參數
- //query.setLong(0, 1l);
- query.setParameter(0, 1l);
- //3> 根據查詢對象獲得查詢結果
- Customer c = (Customer) query.uniqueResult();
-
- System.out.println(c);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //條件查詢
- //命名佔位符
- public void fun4(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1> 書寫HQL語句
- String hql = " from Customer where cust_id = :abc "; // 查詢所有Customer對象
- //2> 根據HQL語句創建查詢對象
- Query query = session.createQuery(hql);
- //設置參數
- query.setParameter("abc", 1l);
- //3> 根據查詢對象獲得查詢結果
- Customer c = (Customer) query.uniqueResult();
-
- System.out.println(c);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //分頁查詢
- public void fun5(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1> 書寫HQL語句
- String hql = " from Customer "; // 查詢所有Customer對象
- //2> 根據HQL語句創建查詢對象
- Query query = session.createQuery(hql);
- //設置分頁信息 limit ?,?
- query.setFirstResult(1);
- query.setMaxResults(1);
- //3> 根據查詢對象獲得查詢結果
- List<Customer> list = query.list();
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
(2)Criteria查詢:也是hibernate特有的語句(適用於單表查詢)。
下面也同樣用例子來進行解析:
- //基本查詢
- public void fun1(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
-
- //查詢所有的Customer對象
- Criteria criteria = session.createCriteria(Customer.class); //參數是實體類,也就是對應的數據庫中的JavaBean
-
- List<Customer> list = criteria.list();
-
- System.out.println(list); //返回多條數據使用
-
- // Customer c = (Customer) criteria.uniqueResult(); //返回唯一的值使用
-
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
- }
- //條件查詢
- //HQL語句中,不可能出現任何數據庫相關的信息的
- // > gt
- // >= ge
- // < lt
- // <= le
- // == eq
- // != ne
- // in in
- // between and between
- // like like
- // is not null isNotNull
- // is null isNull
- // or or
- // and and
- public void fun2(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //創建criteria查詢對象
- Criteria criteria = session.createCriteria(Customer.class);
- //添加查詢參數 => 查詢cust_id爲1的Customer對象
- criteria.add(Restrictions.eq("cust_id", 1l));
- //執行查詢獲得結果
- Customer c = (Customer) criteria.uniqueResult();
- System.out.println(c);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //分頁查詢
- public void fun3(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //創建criteria查詢對象
- Criteria criteria = session.createCriteria(Customer.class);
- //設置分頁信息 limit ?,?
- criteria.setFirstResult(1);
- criteria.setMaxResults(2);
- //執行查詢
- List<Customer> list = criteria.list();
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //查詢總記錄數
- public void fun4(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //創建criteria查詢對象
- Criteria criteria = session.createCriteria(Customer.class);
- //設置查詢的聚合函數 => 總行數
- criteria.setProjection(Projections.rowCount());
- //執行查詢
- Long count = (Long) criteria.uniqueResult();
-
- System.out.println(count);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- }
(3)原生的SQL語句(使用於多表複雜查詢),這和正常的sql操作語句類似
同樣的,下面也通過實際的例子來進行講解:
- //基本查詢
- public void fun1(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1 書寫sql語句
- String sql = "select * from cst_customer";
-
- //2 創建sql查詢對象
- SQLQuery query = session.createSQLQuery(sql);
-
- //3 調用方法查詢結果
- List<Object[]> list = query.list(); //這是原生的SQL返回的類型,在沒有指定返回的類型時候,原生查詢出來的就是object數組類型
- //query.uniqueResult();
-
- for(Object[] objs : list){
- System.out.println(Arrays.toString(objs));
- }
-
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //基本查詢(查詢返回的是JavaBean對象類型)
- public void fun2(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1 書寫sql語句
- String sql = "select * from cst_customer";
-
- //2 創建sql查詢對象
- SQLQuery query = session.createSQLQuery(sql);
- //指定將結果集封裝到哪個對象中
- query.addEntity(Customer.class);
-
- //3 調用方法查詢結果
- List<Customer> list = query.list();
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //條件查詢
- public void fun3(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1 書寫sql語句
- String sql = "select * from cst_customer where cust_id = ? ";
-
- //2 創建sql查詢對象
- SQLQuery query = session.createSQLQuery(sql);
-
- query.setParameter(0, 1l);
- //指定將結果集封裝到哪個對象中
- query.addEntity(Customer.class);
-
- //3 調用方法查詢結果
- List<Customer> list = query.list();
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
- //分頁查詢
- public void fun4(){
- //1 獲得session
- Session session = HibernateUtils.openSession();
- //2 控制事務
- Transaction tx = session.beginTransaction();
- //3執行操作
- //-------------------------------------------
- //1 書寫sql語句
- String sql = "select * from cst_customer limit ?,? ";
-
- //2 創建sql查詢對象
- SQLQuery query = session.createSQLQuery(sql);
-
- query.setParameter(0, 0);
- query.setParameter(1, 1);
- //指定將結果集封裝到哪個對象中
- query.addEntity(Customer.class);
-
- //3 調用方法查詢結果
- List<Customer> list = query.list();
-
- System.out.println(list);
- //-------------------------------------------
- //4提交事務.關閉資源
- tx.commit();
- session.close();// 遊離|託管 狀態, 有id , 沒有關聯
-
-
- }
11:Hibernate中的關係表達
(1)一對多的關係(比如客戶與聯繫人的關係)
客戶的xml中的配置:
- <!-- 集合,一對多關係,在配置文件中配置 -->
- <!--
- name屬性:集合屬性名
- column屬性: 外鍵列名
- class屬性: 與我關聯的對象完整類名
- -->
- <!--
- 級聯操作: cascade
- save-update: 級聯保存更新
- delete:級聯刪除
- all:save-update+delete
- 級聯操作: 簡化操作.目的就是爲了少些兩行代碼.
- -->
- <!-- inverse屬性: 配置關係是否維護.
- true: customer不維護關係
- false(默認值): customer維護關係
-
- inverse屬性: 性能優化.提高關係維護的性能.
- 原則: 無論怎麼放棄,總有一方必須要維護關係.
- 一對多關係中: 一的一方放棄.也只能一的一方放棄.多的一方不能放棄.
- -->
- <set name="linkMens" inverse="true" cascade="delete" >
- <key column="lkm_cust_id" ></key>
- <one-to-many class="LinkMan" />
- </set>
聯繫人的xml中的配置:
- <!-- 多對一端的xml配置(其中那些屬性的配置是和正常的是一樣的都需要進行配置的) -->
- <!--
- name屬性:引用屬性名
- column屬性: 外鍵列名
- class屬性: 與我關聯的對象完整類名
- -->
- <!--
- 級聯操作: cascade
- save-update: 級聯保存更新
- delete:級聯刪除
- all:save-update+delete
- 級聯操作: 簡化操作.目的就是爲了少些兩行代碼.
- -->
- <!-- 多的一方: 不能放棄維護關係的.外鍵字段就在多的一方. -->
- <many-to-one name="customer" column="lkm_cust_id" class="Customer" >
- </many-to-one>
總結:
1、一般情況下,一對多,多的一方維護關係,效率比較高
2、一對多,如果一的一方維護關係,實際上就是發出更新外鍵的update語句
3、如果多的一方維護關係,實際上就是更新了多的一方所對應表的所有的字段
4、一般情況下,一的一方的文件中,針對set集合的invserse的值爲true,不維護關係
(2)多對對關係(比如用戶和角色關係)注意事項:在多對多中,對於表的維護,一定只需要一方進行維護第三方表,而不能兩方都同時維護,會出錯用戶實體的xml配置:
說明:
1、關係操作
增加關係相當於在第三張表中插入一行數據
解除關係相當於在第三張表中刪除一行數據
更新關係 相當於 先刪除後增加
誰維護關係,效率都一樣,看頁面的需求
2、級聯操作
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="cn.itcast.domain" >
- <class name="User" table="sys_user" >
- <id name="user_id" >
- <generator class="native"></generator>
- </id>
- <property name="user_code" ></property>
- <property name="user_name" ></property>
- <property name="user_password" ></property>
- <property name="user_state" ></property>
-
- <!-- 多對多關係表達 -->
- <!--
- name: 集合屬性名
- table: 配置中間表名
- key
- |-column:外鍵,別人引用"我"的外鍵列名
- class: 我與哪個類是多對多關係
- column:外鍵.我引用比人的外鍵列名
- -->
- <!-- cascade級聯操作:
- save-update: 級聯保存更新
- delete:級聯刪除
- all:級聯保存更新+級聯刪除
- 結論: cascade簡化代碼書寫.該屬性使不使用無所謂. 建議要用只用save-update.
- 如果使用delete操作太過危險.尤其在多對多中.不建議使用.
- -->
- <set name="roles" table="sys_user_role" cascade="save-update" >
- <key column="user_id" ></key>
- <many-to-many class="Role" column="role_id" ></many-to-many>
- </set>
-
- </class>
- </hibernate-mapping>
角色實體的xml配置:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="cn.itcast.domain" >
- <class name="Role" table="sys_role" >
- <id name="role_id" >
- <generator class="native"></generator>
- </id>
- <property name="role_name" ></property>
- <property name="role_memo" ></property>
-
- <!-- 使用inverse屬性
- true: 放棄維護外鍵關係
- false(默認值):維護關係
-
- 結論: 將來在開發中,如果遇到多對多關係.一定要選擇一方放棄維護關係.
- 一般誰來放棄要看業務方向. 例如錄入員工時,需要爲員工指定所屬角色.
- 那麼業務方向就是由員工維護角色. 角色不需要維護與員工關係.角色放棄維護
- -->
- <set name="users" table="sys_user_role" inverse="true" >
- <key column="role_id" ></key>
- <many-to-many class="User" column="user_id" ></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
總結:1、多對多的結構是三張表
2、映射文件中,與一對多的配置也不一樣,需要指定一個第三張表的聯繫
3、多對多,誰維護關係,效率都一樣
4、多對多是類與集合的關係
12:查詢的進階操作
(1)HQL語句:
單表查詢操作:
- //基本語法
- @Test
- public void fun1(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql = " from cn.itcast.domain.Customer ";//完整寫法
- String hql2 = " from Customer "; //簡單寫法
- String hql3 = " from java.lang.Object "; //查詢所有的對象實體的語句
-
- Query query = session.createQuery(hql3);
-
- List list = query.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //排序
- public void fun2(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql1 = " from cn.itcast.domain.Customer order by cust_id asc ";//完整寫法
- String hql2 = " from cn.itcast.domain.Customer order by cust_id desc ";//完整寫法
-
- Query query = session.createQuery(hql2);
-
- List list = query.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //條件查詢
- public void fun3(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql1 = " from cn.itcast.domain.Customer where cust_id =? ";//完整寫法
- String hql2 = " from cn.itcast.domain.Customer where cust_id = :id ";//完整寫法
-
- Query query = session.createQuery(hql2);
-
- // query.setParameter(0, 2l);
- query.setParameter("id", 2l);
-
-
- List list = query.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //分頁查詢
- public void fun4(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql1 = " from cn.itcast.domain.Customer ";//完整寫法
-
- Query query = session.createQuery(hql1);
-
- //limit ?,?
- // (當前頁數-1)*每頁條數
- query.setFirstResult(2);
- query.setMaxResults(2);
-
- List list = query.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //統計查詢
- //count 計數
- //sum 求和
- //avg 平均數
- //max
- //min
- public void fun5(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql1 = " select count(*) from cn.itcast.domain.Customer ";//完整寫法
- String hql2 = " select sum(cust_id) from cn.itcast.domain.Customer ";//完整寫法
- String hql3 = " select avg(cust_id) from cn.itcast.domain.Customer ";//完整寫法
- String hql4 = " select max(cust_id) from cn.itcast.domain.Customer ";//完整寫法
- String hql5 = " select min(cust_id) from cn.itcast.domain.Customer ";//完整寫法
-
- Query query = session.createQuery(hql5);
-
- Number number = (Number) query.uniqueResult(); //這裏用了Number類型來接受,主要是考慮上面可能出現Long和Int型,在實際中用對應的字段類型即可。
-
- System.out.println(number);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //投影查詢
- public void fun6(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql1 = " select cust_name from cn.itcast.domain.Customer "; //查詢某個字段的內容數據,返回的是對應字段的類型數據
- String hql2 = " select cust_name,cust_id from cn.itcast.domain.Customer "; //查詢多個字段的內容,返回的是object[] 的數組類型數據
- String hql3 = " select new Customer(cust_id,cust_name) from cn.itcast.domain.Customer "; //查詢多個字段,並且返回的是對象類型的數據。通過這樣的方式,返回的是customer對象,注意必須在對應的實體中,存在對於的構造方法,否則報錯。
-
- Query query = session.createQuery(hql3);
-
- List list = query.list();
-
- System.out.println(list);
-
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
編寫一個非常強大的Dao層的一個方法,實現能夠通用查詢(也就是隻要給實體類和查詢數據,就能夠實現對應表的數據的查詢,這個在DAO層的查詢方法非常方便)
- private void testQueryClasses_Where_AnyCondition(Class className,Map<String, String> variables){
-
- StringBuffer stringBuffer = new StringBuffer();
- /**
- * 通過className得到該實體類的字符串形式
- */
- stringBuffer.append("from "+sessionFactory.getClassMetadata(className).getEntityName());
- stringBuffer.append(" where 1=1");
- /**
- * 動態的拼接查詢語句,如果一個屬性的值爲"",則不往條件中添加
- */
- for (Entry<String, String> entry : variables.entrySet()) {
- if(!entry.getValue().equals("")){//如果屬性不爲""
- stringBuffer.append(" and "+entry.getKey()+"=:"+entry.getKey());
- }
- }
- Session session = sessionFactory.openSession();
- Query query = session.createQuery(stringBuffer.toString());
- /**
- * 動態的給條件賦值
- */
- for (Entry<String, String> entry : variables.entrySet()) {
- if(!entry.getValue().equals("")){
- query.setParameter(entry.getKey(), entry.getValue());
- }
- }
- List<Classes> classes = query.list();
- System.out.println(classes.size());
- session.close();
- }
-
- @Test
- public void testQueryEntry_Where_AnyCondition(){
- /**
- * Map<String,String>
- * key爲持久化對象的屬性
- * value爲持久化對象的屬性的值
- */
- Map<String, String> variables = new HashMap<String, String>();
- variables.put("name", "");
- variables.put("description", "");
- this.testQueryClasses_Where_AnyCondition(Classes.class,variables);//只需要傳入實體類的類和數據,就能夠實現相應的查詢
- }
這裏的話,在介紹一個Hibernate中獲取元數據(就是相當於數據庫中的字段等信息,數據字典的內容)的一個方法。------------------------至少要了解這個
- /**
- * 元數據
- * 數據倉庫
- */
- @Test
- public void testClassMetaData(){
- /**
- * ClassMetaData可以得到持久化類的信息
- * 標示符的名稱
- * 一般屬性的名稱
- * 。。。。。
- */
- Map<String,ClassMetadata> map = sessionFactory.getAllClassMetadata();
- for (Entry<String, ClassMetadata> entry : map.entrySet()) {
- System.out.println(entry.getKey());
- ClassMetadata classMetadata = entry.getValue();
- System.out.println("entityName:"+classMetadata.getEntityName()); //獲取到對應實體的類名
- System.out.println("identityName:"+classMetadata.getIdentifierPropertyName()); //獲取到主鍵的名字
- String[] propertiesNames = classMetadata.getPropertyNames(); //獲取到實體類對應數據庫中的名稱
- for (String string : propertiesNames) {
- System.out.println(string);
- }
- }
- ClassMetadata classMetadata = sessionFactory.getClassMetadata(Classes.class);
- System.out.println(classMetadata.getEntityName());
- }
HQL中的多表查詢語法:
先貼一下關於多表查詢的一些知識點:
- //回顧-原生SQL
- // 交叉連接-笛卡爾積(避免)
- // select * from A,B
- // 內連接
- // |-隱式內連接
- // select * from A,B where b.aid = a.id
- // |-顯式內連接
- // select * from A inner join B on b.aid = a.id
- // 外連接
- // |- 左外
- // select * from A left [outer] join B on b.aid = a.id
- // |- 右外
- // select * from A right [outer] join B on b.aid = a.id
HQL的多表查詢:
- //HQL 內連接 => 將連接的兩端對象分別返回.放到數組中.
- public void fun1(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql = " from Customer c inner join c.linkMens ";
-
- Query query = session.createQuery(hql);
-
- List<Object[]> list = query.list();
-
- for(Object[] arr : list){
- System.out.println(Arrays.toString(arr));
- }
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //HQL 迫切內連接 => 幫我們進行封裝.返回值就是一個對象
- public void fun2(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql = " from Customer c inner join fetch c.linkMens ";
-
- Query query = session.createQuery(hql);
-
- List<Customer> list = query.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //HQL 左外連接 => 將連接的兩端對象分別返回.放到數組中.
- public void fun3(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql = " from Customer c left join c.linkMens ";
-
- Query query = session.createQuery(hql);
-
- List<Object[]> list = query.list();
-
- for(Object[] arr : list){
- System.out.println(Arrays.toString(arr));
- }
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
- //HQL 右外連接 => 將連接的兩端對象分別返回.放到數組中.
- public void fun4(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- String hql = " from Customer c right join c.linkMens ";
-
- Query query = session.createQuery(hql);
-
- List<Object[]> list = query.list();
-
- for(Object[] arr : list){
- System.out.println(Arrays.toString(arr));
- }
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
(2)Criteria查詢語法:
基本查詢:
離線查詢的Criteria(很方便):
用一個小例子來解析上面的這個圖的內容:
- public void fun1(){
- //模擬爲Service/web層
- DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
-
- dc.add(Restrictions.idEq(6l));//拼裝條件(全部與普通Criteria一致)
-
- //----------------------------------------------------
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
- Criteria c = dc.getExecutableCriteria(session);
-
- List list = c.list();
-
- System.out.println(list);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
下面的13,14,15這三個小點的內容都是屬於查詢優化(包括單表,一對多的關係,多對多的關係)中的內容哦,可以看看!!!!!這個在面試的時候一般用於回答Hibernate可以從哪些方面進行優化效率!!!
13:類級別的加載策略(立即加載和懶加載策略)
立即加載:當session進行使用get方法時,立即進行數據庫對應的查詢操作
懶加載:當session進行load方法時,並不是直接馬上進行數據庫的操作,而是產生一個代理對象,當使用這個對象的時候,才進行真正的數據庫的操作。
(1)session的get()方法。(不存在懶加載策略,只有立即加載策略)
- // get方法 : 立即加載.執行方法時立即發送sql語句查詢結果
- public void fun1(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
-
- Customer c = session.get(Customer.class, 2l);
-
- System.out.println(c);
- //----------------------------------------------------
- tx.commit();
- session.close();
-
- }
(2)session的load()方法(存在懶加載策略,根據設置的xml中的屬性來決定)
- // load方法(默認):是在執行時,不發送任何sql語句.返回一個對象.使用該對象時,才執行查詢.
- // 延遲加載: 僅僅獲得沒有使用.不會查詢.在使用時才進行查詢.
- // 是否對類進行延遲加載: 可以通過在class元素上配置lazy屬性來控制.
- //lazy:true 加載時,不查詢.使用時才查詢b
- //lazy:false 加載時立即查詢.
- public void fun2(){
- Session session = HibernateUtils.openSession();
- Transaction tx = session.beginTransaction();
- //----------------------------------------------------
-
- Customer c = session.load(Customer.class, 2l);
-
- //----------------------------------------------------
- tx.commit();
- session.close();
- System.out.println(c);
-
- }
在對應的實體的xml中進行配置
上面的lazy屬性可以爲:true(實施懶加載策略);false(不實施懶加載策略);extra(針對需要進行什麼操作,就發出對應的SQL語句,比較有針對性,比如查數據的條數,那麼就只會發出select count from XXXX這種語句)三種
結論:懶加載策略是爲了提高效率(關鍵就是控制SQL語句是什麼時候進行發出)。但是要注意的就是,再進行懶加載策略的時候要確保session是打開的,否則會拋出異常。
14:關聯級別的策略(抓取策略)
(1)集合策略(也就是一對多的關係中存在的策略,這裏是配置多的那一方的內容)
xml中的配置
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="cn.itcast.domain" >
- <class name="Customer" table="cst_customer" lazy="false" >
- <id name="cust_id" >
- <generator class="native"></generator>
- </id>
- <property name="cust_name" column="cust_name" ></property>
- <property name="cust_source" column="cust_source" ></property>
- <property name="cust_industry" column="cust_industry" ></property>
- <property name="cust_level" column="cust_level" ></property>
- <property name="cust_linkman" column="cust_linkman" ></property>
- <property name="cust_phone" column="cust_phone" ></property>
- <property name="cust_mobile" column="cust_mobile" ></property>
-
- <!--
- lazy屬性: 決定是否延遲加載
- true(默認值): 延遲加載,懶加載
- false: 立即加載
- extra: 極其懶惰
- fetch屬性: 決定加載策略.使用什麼類型的sql語句加載集合數據
- select(默認值): 單表查詢加載
- join: 使用多表查詢加載集合
- subselect:使用子查詢加載集合
- -->
- <set name="linkMens" fetch="select" lazy="true" >
- <key column="lkm_cust_id" ></key>
- <one-to-many class="LinkMan" />
- </set>
-
-
- </class>
- </hibernate-mapping>
由於上面的fetch和lazy屬性分別都有3種,那麼組合起來就有9種情況的加載方式,所以下面都分別進行講解一下。
(2)關聯屬性策略(就是一對多關係中的,所對應一的那一方的策略)
一對多關係中,一的那方的xml中的配置信息:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="cn.itcast.domain" >
- <class name="LinkMan" table="cst_linkman" >
- <id name="lkm_id" >
- <generator class="native"></generator>
- </id>
- <property name="lkm_gender" ></property>
- <property name="lkm_name" ></