Hibernate基礎知識(2)

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();
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章