參考代碼下載github:https://github.com/changwensir/java-ee/tree/master/hibernate4
1、建立Hibernate.cfg.xml設定檔
<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- 配置串連資料庫的基本資料 jdbc:mysql://localhost:3306/utils--><!-- <property name="connection.url">jdbc:mysql://localhost/hibernate1</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property>--> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <!-- 配置 utils 的基本資料 --> <!-- utils 所使用的資料庫方言 MySQL5Dialect--> <!--<property name="dialect">org.utils.dialect.MySQLInnoDBDialect</property>--> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <!-- 執行操作時是否在控制台列印 SQL --> <property name="show_sql">true</property> <!-- 是否對 SQL 進行格式化,例如語句顯示會換行 --> <property name="format_sql">true</property> <!-- 指定自動產生資料表的策略 --> <property name="hbm2ddl.auto">update</property> <!-- 配置 C3P0 資料來源--> <!--資料庫連接池的最大串連數--> <property name="hibernate.c3p0.max_size">10</property> <!--資料庫連接池的最小串連數--> <property name="hibernate.c3p0.min_size">5</property> <!--當資料庫連接池中的串連耗盡時, 同一時刻擷取多少個資料庫連接--> <property name="c3p0.acquire_increment">2</property> <!--表示串連池檢測線程多長時間檢測一次池內的所有連結化物件是否逾時. 串連池本身不會把自己從串連池中移除,而是專門有一個線程按照一定的時間間隔來做這件事, 這個線程通過比較連線物件最後一次被使用時間和目前時間的時間差來和 timeout 做對比,進而決定是否銷毀這個連線物件。--> <property name="c3p0.idle_test_period">2000</property> <!--資料庫連接池中連線物件在多長時間沒有使用過後,就應該被銷毀--> <property name="c3p0.timeout">2000</property> <!--緩衝 Statement 對象的數量--> <property name="c3p0.max_statements">10</property> <!-- 設定 JDBC 的 Statement 讀取資料的時候每次從資料庫中取出的記錄條數 ,取100最好--> <property name="hibernate.jdbc.fetch_size">100</property> <!-- 設定對資料庫進行大量刪除,批次更新和批量插入的時候的批次大小 取20合適--> <property name="jdbc.batch_size">30</property> <mapping resource="hbm/News.hbm.xml"/> </session-factory></hibernate-configuration>
hbm2ddl.auto:該屬性可協助程式員實現正向工程, 即由 java 代碼產生資料庫指令碼, 進而產生具體的表結構. 。取值 create | update | create-drop | validate
- create : 會根據 .hbm.xml 檔案來產生資料表, 但是每次運行都會刪除上一次的表 ,重建表, 哪怕二次沒有任何改變
- create-drop : 會根據 .hbm.xml 檔案產生表,但是SessionFactory一關閉, 表就自動刪除
- update : 最常用的屬性值,也會根據 .hbm.xml 檔案產生表, 但若 .hbm.xml 檔案和資料庫中對應的資料表的表結構不同, Hiberante 將更新資料表結構,但不會刪除已有的行和列
- validate : 會和資料庫中的表進行比較, 若 .hbm.xml 檔案中的列在資料表中不存在,則拋出異常
format_sql:是否將 SQL 轉化為格式良好的 SQL . 取值 true | false
1-1.Hibernate設定檔 Hibernate 設定檔主要用於設定資料庫串連和 Hibernate 運行時所需的各種屬性
每個 Hibernate 設定檔對應一個 Configuration 對象
Hibernate設定檔可以有兩種格式:
- hibernate.properties(不推薦)
- hibernate.cfg.xml
hibernate.cfg.xml的常用屬性
1).JDBC 串連屬性
- connection.url:資料庫URL
- connection.username:資料庫使用者名稱
- connection.password:資料庫使用者密碼
- connection.driver_class:資料庫JDBC驅動
- dialect:設定資料庫的方言,根據底層的資料庫不同產生不同的 sql 語句,Hibernate 會針對資料庫的特性在訪問時進行最佳化
2).C3P0 資料庫連接池屬性
- hibernate.c3p0.max_size: 資料庫連接池的最大串連數
- hibernate.c3p0.min_size: 資料庫連接池的最小串連數
- hibernate.c3p0.timeout: 資料庫連接池中連線物件在多長時間沒有使用過後,就應該被銷毀
- hibernate.c3p0.max_statements: 緩衝 Statement 對象的數量
- hibernate.c3p0.idle_test_period: 表示串連池 檢測線程多長時間檢測一次池內的所有連結化物件是否逾時. 串連池本身不會把自己從串連池中移除,而是專門有一個線程按照一定的時間間隔來做這件事,這個線程通過比較連線物件最後一次被使用時間和目前時間的時間差來和 timeout 做對比,進而決定是否銷毀這個連線物件。
- hibernate.c3p0.acquire_increment: 當資料庫連接池中的串連耗盡時, 同一時刻擷取多少個資料庫連接
- show_sql:是否將運行期產生的SQL輸出到日誌以供調試。取值 true | false
- format_sql:是否將 SQL 轉化為格式良好的 SQL . 取值 true | false
- hbm2ddl.auto:在啟動和停止時自動地建立,更新或刪除資料庫模式。取值 create | update | create-drop | validate
- hibernate.jdbc.fetch_size
- hibernate.jdbc.batch_size
3).jdbc.fetch_size 和 jdbc.batch_size
hibernate.jdbc.fetch_size:實質是調用 Statement.setFetchSize() 方法 設定 JDBC 的 Statement 讀取資料的時候每次從資料庫中取出的記錄條數。
- 例如一次查詢1萬條記錄,對於Oracle的JDBC驅動來說,是不會 1 次性把1萬條取出來的,而只會取出 fetchSize 條數,當結果集遍曆完了這些記錄以後,再去資料庫取 fetchSize 條資料。因此大大節省了無謂的記憶體消耗。Fetch Size設的越大,讀資料庫的次數越少,速度越快;Fetch Size越小,讀資料庫的次數越多,速度越慢。Oracle資料庫的JDBC驅動預設的Fetch Size = 10,是一個保守的設定,根據測試,當Fetch Size=50時,效能會提升1倍之多, 當 fetchSize=100,效能還能繼續提升20%,Fetch Size繼續增大,效能提升的就不顯著了。並不是所有的資料庫都支援Fetch Size特性,例如MySQL就不支援
hibernate.jdbc.batch_size: 設定對資料庫進行大量刪除,批次更新和批量插入的時候的批次大小,類似於設定緩衝區大小的意思。batchSize 越大,大量操作時向資料庫發送sql的次數越少,速度就越快。
- 測試結果是當Batch Size=0的時候,使用Hibernate對Oracle資料庫刪除1萬條記錄需要25秒,Batch Size = 50的時候,刪除僅僅需要5秒。Oracle資料庫 batchSize=30 的時候比較合適。
2、建立持久化對象
public class News { private Integer id; private String title; private String author; private Date occurrenceDate; public News(String title, String author, Date occurrenceDate) { super(); this.title = title; this.author = author; this.occurrenceDate = occurrenceDate; } public News() { }//省去get,set方法}
建立持久化 Java 類
- 提供一個無參的構造器:使Hibernate可以使用Constructor.newInstance() 來執行個體化持久化類
- 提供一個識別屬性(identifier property): 通常映射為資料庫表的主鍵欄位. 如果沒有該屬性,一些功能將不起作用,如:Session.saveOrUpdate()
為類的持久化類欄位聲明存取方法(get/set): Hibernate對JavaBeans 風格的屬性實行持久化。
- 使用非 final 類: 在運行時組建代理程式是 Hibernate 的一個重要的功能. 如果持久化類沒有實現任何介面, Hibnernate 使用 CGLIB 組建代理程式. 如果使用的是 final 類, 則無法產生 CGLIB 代理.
- 重寫 eqauls 和 hashCode 方法: 如果需要把持久化類的執行個體放到 Set 中(當需要進行關聯映射時), 則應該重寫這兩個方法
Hibernate 不要求持久化類繼承任何父類或實現介面,這可以保證代碼不被汙染。這就是Hibernate被稱為低侵入式設計的原因
Hibernate 採用 XML 格式的檔案來指定對象和關係資料之間的映射. 在運行時 Hibernate 將根據這個對應檔來產生各種 SQL 陳述式
對應檔的副檔名為 .hbm.xml
3、建立對象--對應檔
建立完後,需要所這個檔案配置到hibernate.cfg.xml裡
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.changwen.hibernate4.session.sessionPojo"> <class name="News" table="NEWS" dynamic-update="true"> <!-- name的內容是這個類的屬性名稱--> <id name="id" type="java.lang.Integer"> <!-- name的內容是資料庫的欄位名(列名)--> <column name="ID" /> <!-- 指定主鍵產生的方式,native: 使用資料庫本地方法,如Mysql使用自增,Oracle使用序列--> <generator class="native" /> </id> <property name="title" type="string" column="TITLE" unique="true" update="false" index="news_index" length="20"> </property> <property name="author" type="java.lang.String" index="news_index"> <column name="AUTHOR" /> </property> <property name="occurrenceDate" type="java.util.Date"> <column name="occurrenceDate" /> </property> </class></hibernate-mapping>
4、測試訪問資料庫
後面的測試都以這個為基礎,請注意
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init(){ // 建立 Configuration 對象: 對應 utils 的基本配置資訊和 對象關係映射資訊 Configuration configuration = new Configuration().configure(); // 建立一個 ServiceRegistry 對象: utils 4.x 新添加的對象 //utils 的任何配置和服務都需要在該對象中註冊後才能有效. ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); //建立一個 Session 對象 session = sessionFactory.openSession(); //開啟事務 transaction = session.beginTransaction(); } @After public void destroy(){ //提交事務 :真正與資料庫互動的語句 transaction.commit(); //關閉 Session session.close(); //關閉 SessionFactory 對象 sessionFactory.close(); }<pre name="code" class="java"> @Test public void test() { }
如果建立表成功就完成本執行個體
4-1.Configuration 類
Configuration 類負責管理 Hibernate 的配置資訊。包括如下內容:
- Hibernate 啟動並執行底層資訊:資料庫的URL、使用者名稱、密碼、JDBC驅動類,資料庫Dialect,資料庫連接池等(對應 hibernate.cfg.xml 檔案)。
- 持久化類與資料表的映射關係(*.hbm.xml 檔案)
建立 Configuration 的兩種方式
- 屬性檔案(hibernate.properties):
·Configuration cfg = new Configuration();
- Xml檔案(hibernate.cfg.xml)
·Configuration cfg = new Configuration().configure();
- Configuration 的 configure 方法還支援帶參數的訪問:
·File file = new File(“simpleit.xml”);
·Configuration cfg = new Configuration().configure(file);
4-2.SessionFactory 介面
- 針對單個資料庫映射關係經過編譯後的記憶體鏡像,是安全執行緒的。
- SessionFactory 對象一旦構造完畢,即被賦予特定的配置資訊
- SessionFactory是產生Session的工廠
- 構造 SessionFactory 很消耗資源,一般情況下一個應用中只初始化一個 SessionFactory 對象。
- Hibernate4 新增了一個 ServiceRegistry 介面,所有基於 Hibernate 的配置或者服務都必須統一向這個 ServiceRegistry 註冊後才會生效
- Hibernate4 中建立 SessionFactory 的步驟見測試類別前三條代碼
4-3.Session 介面
Session 是應用程式與資料庫之間互動操作的一個單線程對象,是 Hibernate 運作的中心,所有持久化對象必須在 session 的管理下才可以進行持久化操作。此對象的生命週期很短。Session 對象有一個一級緩衝,顯式執行 flush 之前,所有的持久層操作的資料都緩衝在 session 對象處。相當於 JDBC 中的 Connection。
持久化類與 Session 關聯起來後就具有了持久化的能力。
Session 類的方法:
-取得持久化對象的方法: get() load()
-持久化對象都得儲存,更新和刪除:save(),update(),saveOrUpdate(),delete()
-開啟事務: beginTransaction().
-管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等
4-4.Transaction(事務)
代表一次原子操作,它具有資料庫事務的概念。所有持久層都應該在交易管理下進行,即使是唯讀操作。
Transaction tx = session.beginTransaction();
常用方法:
commit():提交相關聯的session執行個體
rollback():撤銷事務操作
wasCommitted():檢查事務是否提交