Hibernate 核心配置和核心API
1、 hibernate體系結構
Hibernate位於應用程序和數據庫之間,將數據庫底層完全封裝,應用程序只需要操作持久化對象(Persistent Object),通過Hibernate生成SQL語句,完成對數據表中記錄的操作。
hibernate 支持兩種核心配置文件:
src/hibernate.properties(key-value文件鍵值對,主要配置Hibernate基本屬性)
hibernate.connection.driver_class=com.mysql.jdbc.Driver
src/hibernate.cfg.xml (完成基本屬性配置,加載hbm映射文件)
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<mapping resource="lsq/hibernate/domain/Customer.hbm.xml"/> 加載hbm映射
* hibernate.properties 無法加載 hbm映射 , 採用properties方式,必須手動編程加載 hbm文件或者 持久化類
2、 hibernate的常用屬性
必須屬性
hibernate.dialect 操作數據庫方言
hibernate.connection.driver_class 連接數據庫驅動程序
hibernate.connection.url 連接數據庫URL
hibernate.connection.username 數據庫用戶名
hibernate.connection.password 數據庫密碼
可選屬性
hibernate.show_sql true 在控制檯上輸出SQL語句
* hibernate 自己完成的,並沒有使用日誌系統 ,當關閉日誌後,控制檯仍然有SQL語句
hibernate.format_sql true 格式化控制檯輸出的SQL語句
* SQL 會自動換行,對於比較長的sql 查看方便
hibernate.hbm2ddl.auto create/create-drop/update/validate DDL策略
* DDL 主要建表語句,和表結構更新語句
create:表示啓動的時候先drop,再create (測試人員 準備標準測試數據)
create-drop: 也表示創建,只不過再系統關閉前執行一下drop (測試程序是否正確)
update: 這個操作啓動的時候會去檢查schema是否一致,如果不一致會做scheme更新 (建表,更新表結構【只能加】)
validate: 啓動時驗證現有schema與你配置的hibernate是否一致,如果不一致就拋出異常,並不做更新
*** 在產品開發中 update 和 validate 使用較多
hibernate.connection.autocommit true 事務是否自動提交
* 用於解決 沒有開啓事務的操作時,事務如何自動處理
* 默認事務 自動回滾
3、 Hibernate 核心 API 詳解
1) Configuration : 加載hibernate 配置
加載 hibernate.properties 和 hibernate.cfg.xml
持久化類與數據表的映射關係(*.hbm.xml 文件)
加載核心屬性配置:
方式一:Configuration cfg = new Configuration(); 去src 讀取 hibernate.properties 屬性配置文件
方式二:Configuration cfg = new Configuration().configure(); 去src讀取 hibernate.cfg.xml,
Configuration cfg = new Configuration().configure("自定義文件.xml"); 去src 加載指定文件
手動加載hbm映射配置:
如果沒有對PO類進行hbm映射,運行時會報錯:org.hibernate.MappingException: Unknown entity: lsq.hibernate.domain.Customer
需要手動加載hbm文件:
configuration.addResource("lsq/hibernate/domain/Customer.hbm.xml"); 加載hbm文件
或者
configuration.addClass(Customer.class); 加載Class,自動搜索hbm映射文件
** 如果使用 hibernate.cfg.xml配置,將映射配置xml中 <mapping resource="lsq/hibernate/domain/Customer.hbm.xml"/>
2)SessionFactory
Hibernate操作數據庫,它的核心對象是Session,但是要想得到Session,需要先構造SessionFactory。
SessionFactory保存了當前的數據庫配置信息和所有映射關係以及預定義的SQL語句。
預定義SQL:
在配置文件中定義SQL,給SQL命名,在程序中通過預定義SQL名稱(login)使用SQL
<sql-query name="login">
<![CDATA[select * from user where username= ? and password =?]]>
</sql-query>
SessionFactory對象是線程安全的。
SessionFactory負責維護Hibernate的二級緩存。
主要API:
Session openSession():隨機從內部維護連接池中獲取一個連接,構造Session對象。
Session getCurrentSession():獲得一個與線程綁定Session的對象。(ThreadLocal)
SessionFactory內部維護數據庫連接池很浪費資源,通常一個應用程序只有一個SessionFactory對象。
*抽象一個HibernateUtils工具類,確保只有一個SessionFactory(Static)
SessionFactory默認使用連接池時內置連接池,由DriverManagerConnectionProvider 類提供
* DriverManagerConnectionProvider 內部使用 DriverManager.getConnection 獲得連接
package lsq.hibernate.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate操作工具類,只創建一個SessionFactory
* @author Daniel Li
*
*/
public class HibernateUtils {
private static Configuration configuration;
private static SessionFactory sessionFactory;
static{
//只對SessionFactory初始化一次
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
/**
* 獲得Hibernate操作會話對象
* @return
*/
public static Session openSession(){
return sessionFactory.openSession();
}
}
配置c3p0連接池:
第一步 導入 c3p0-0.9.1.jar
第二步 在hibernate.cfg.xml 修改連接提供者
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
第三步 (選作) 配置c3p0連接池屬性
<property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">20</property>
<property name="c3p0.timeout">120</property>
<property name="c3p0.idle_test_period">3000</property>
3)Session
代表hibernate操作會話對象,相當於 Connection。
Session是應用程序與數據庫之間交互操作的一個單線程對象,是Hibernate運作的中心。線程不安全(在方法內部定義和使用Session,不會出現線程問題)
Session進行PO對象的常見持久化操作,存在一級緩存。
常用方法:
save():插入;
update():完成修改;
delete():完成刪除;
get/load():根據主鍵字段查詢;
createQuery、createSQLQuery:創建查詢對象,Query接收HQL,SQLQuery接收SQL;
createCriteria():面向對象條件查詢
4)Transaction
commit():提交相關聯的session實例。
rollback():撤銷事務操作。
wasCommitted():檢查事務是否提交。
如果沒有開啓事務,那麼每個Session的操作,都相當於一個獨立的事務。
*設置事務是否提交
<property name="hibernate.connection.autocommit">false</property> 事務不提交
<property name="hibernate.connection.autocommit">true</property> 事務提交
默認false
5)Query
Query代表面向對象的一個Hibernate查詢操作。session.createQuery() 獲得,接收參數 HQL語句
步驟:
獲得Hibernate Session對象
編寫HQL語句
調用session.createQuery 創建查詢對象
如果HQL語句包含參數,則調用Query的setXXX設置參數
調用Query對象的list() 或uniqueResult() 方法執行查詢
Query還包含兩個方法用於控制返回結果。
setFirstResult(int firstResult):設置返回結果從第幾條開始。
setMaxResults(int maxResults):設置返回結果記錄條數。
案例一:查詢所有數據 from Customer;
案例二:分頁查詢
案例三:通過select關鍵字,查詢指定屬性對應列
select name,age from Customer; 返回每條數據 保存 Object[] ----- List<Object[]>(返回的每條數據會保存到對象數組中,最後返回List)
如果想將查詢結果,保存Customer對象中--->使用構造方法 !!!!!(在Customer類中,定義name和age屬性構造器)
select new Customer(name,age) from Customer
案例四:通過where語句添加查詢條件
無名字參數 from Customer where name= ? ; 設置參數 query.setParameter(0,"Curry");
有名字參數 from Customer where name= :myname; 設置參數 query.setParameter("myname","Curry");
package lsq.hibernate.test;
import java.util.List;
import lsq.hibernate.domain.Customer;
import lsq.hibernate.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
/**
* Hibernate的查詢操作Query、Criteria
* @author Daniel Li
*
*/
public class HibernateTest2 {
//使用Query對象的查詢
@Test
public void testQuery(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
//1、查詢所有數據
String hql = "from Customer";
Query query = session.createQuery(hql);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//批量插入100條數據
@Test
public void testBatchInsert(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
for (int i = 0; i < 100; i++) {
Customer customer = new Customer();
customer.setName("name"+i);
customer.setAge(i);
customer.setCity("北京");
session.save(customer);
}
transaction.commit();
session.close();
}
//使用Query對象實現分頁查詢
@Test
public void testQueryPage(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
String hql = "from Customer";
Query query = session.createQuery(hql);
query.setFirstResult(20);//索引20代表第21條數據
query.setMaxResults(10);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query對象查詢指定屬性對應列
@Test
public void testQuerySpecifiedColumn(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
//這裏name和age是
// String hql = "select name,age from Customer";
String hql = "select new Customer(name,age) from Customer";
Query query = session.createQuery(hql);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query對象查詢帶有條件的查詢(匿名參數)
@Test
public void testQueryCondition1(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
//匿名參數
String hql = "from Customer where name = ? and age = ?";
Query query = session.createQuery(hql);
//設置參數
query.setParameter(0, "Curry");
query.setParameter(1, 28);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
//使用Query對象查詢帶有條件的查詢(有名稱的參數)
@Test
public void testQueryCondition2(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
//匿名參數
String hql = "from Customer where name = :cname and age = :cage";
Query query = session.createQuery(hql);
//設置參數
query.setParameter("cname", "Curry");
query.setParameter("cage", 28);
List<Customer> list = query.list();
System.out.println(list);
transaction.commit();
session.close();
}
}
6)Criteria接口
主要爲了解決多條件查詢問題,以面向對象的方式添加條件,無需拼接HQL語句
獲得對象
Criteria criteria = session.createCriteria(Customer.class);
步驟
獲得Hibernate的Session對象
通過Session獲得Criteria對象
使用Restrictions的靜態方法創建Criterion條件對象
向Criteria對象中添加Criterion 查詢條件
執行Criterita的 list() 或uniqueResult() 獲得結果
* Criteria查詢 可以實現 和Query 一樣效果
案例一 查詢所有
Criteria criteria = session.createCriteria(Customer.class);
案例二 分頁
criteria.setFirstResult(1);
criteria.setMaxResults(2);
案例三 條件查詢
criteria.add(Restrictions.eq("name", "Curry"));
criteria.add(Restrictions.lt("age", 30));
criteria.add(Restrictions.like("name", "C%"));
** 當多條件組合查詢時,criteria 更加方便
package lsq.hibernate.test;
import java.util.List;
import lsq.hibernate.domain.Customer;
import lsq.hibernate.utils.HibernateUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
/**
* 使用Criteria查詢
* @author Daniel Li
*
*/
public class HibernateTest3 {
@Test
public void testCriteria(){
//獲得session
Session session = HibernateUtils.openSession();
//開啓事務
Transaction transaction = session.beginTransaction();
//1、查詢所有數據
// Criteria criteria = session.createCriteria(Customer.class);
// List<Customer> list = criteria.list();
// System.out.println(list);
//2、分頁查詢
// Criteria criteria = session.createCriteria(Customer.class);
// criteria.setFirstResult(1);
// criteria.setMaxResults(2);
// List<Customer> list = criteria.list();
// System.out.println(list);
//3、帶有查詢條件的查詢
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "Curry"));
criteria.add(Restrictions.lt("age", 30));
List<Customer> list = criteria.list();
System.out.println(list);
transaction.commit();
session.close();
}
}