程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Hibernate簡介,hibernate

Hibernate簡介,hibernate

編輯:JAVA綜合教程

Hibernate簡介,hibernate


一、概述

Hibernate是一個開放源代碼的的對象關系映射框架。它對jdbc進行了封裝,提供了強大,高性能的對象關系模型數據庫的持久化服務。Hibernate提供的HQL(Hibernate Query Language)是面向對象的查詢語言,它在對象模型數據和關系型數據庫之間構建了一條快速,高效,便捷的溝通渠道。

二、Hibernate框架

1.ORM(Object Relation Mapping)稱對象關系映射

在編寫程序的時候,以面向對象的方式處理數據,在保存數據的時候,卻以關系型數據的形式存儲到數據庫中,所以需要一種能在兩者間進行數據轉換的機制,這種機制稱對象-關系映射機制,簡稱ORM.

2.實體對象的狀態

>自由態

自由狀態就是實體對象在內存中自由存在,此時它與數據庫無關,自由狀態有兩個特性:

(1).不處於Session的緩存中,也就是不被任何一個Session實例關聯。

(2).在數據中沒有對應的記錄。

>持久態

持久狀態就是實體對象在Hibernate的管理情況下的狀態。在持久狀態下,實體對象的引用被納入Hibernate實體容器中加以管理。處於持久狀態的實體對象會被Hibernate固化到數據庫中。持久狀態的特性:

(1).位於一個Session實例的緩存中,也就是說,持久化對象總被一個Session實例關聯。

(2).持久化對象和數據庫中的相關記錄對應。

(3).Session在清理緩存時,會根據持久化對象的屬性變化來同步更新數據庫。

(4).Session的Save()方法把實體對象從自由狀態轉變為持久狀態。

(5).Session的load()方法或get()方法返回的實體對象總是持久狀態。

(6).Session的update(),saveOrUpdate()和lock()方法使實體對象從游離狀態轉變被持久狀態。

>游離態

當處於持久狀態的實體對象,其對應的Session關閉以後,這個實體就處於游離狀態,可以認為Session對象是實體對象在持久狀態的宿主,而實體對象失去這個宿主,也就是這個宿主失效,那這個實體對象就處於游離狀態。游離狀態的特性:

(1).不再位於Session的緩存中,也可以說游離狀態的實體對象不被Session關聯。

(2).游離狀態是由持久化變來的,因此在數據庫中可能還存在與它對應的記錄。

3.VO與PO

處於自由狀態和游離狀態下的實體對象稱為值對象(Value Object,VO).

處於持久狀態的實體對象稱為持久對象(Persistent Object,PO).

VO和PO之間的區別:

1.VO對象包含兩種狀態,即自由狀態和游離狀態,是相對獨立的對象,處於非管理狀態。

2.PO對象處於持久狀態,是Hibernate納入其管理容器的對象,對應數據庫中某條記錄的Hibernate實體,PO的變化在事物提交的時將反映到數據庫中。

3.如果一個PO與其對應的Session實例分離,就會變成VO.

三、Session管理

Session接口是Hibernate向應用程序提供的操作數據庫的最主要的接口,它提供了基本的保存,更新,刪除和加載Java對象的方法。

Session是由SessionFactory創建的,而SessionFactory的實現是線程安全的,也就是說,多個並發的線程可以同時訪問一個SessionFactory並從其中獲取Session實例,但Session不是線程安全的,Session中包含了數據庫操作的相關信息,所以多個線程共享一個Session將會發生數據共享混亂。

3.1、ThreadLocal模式解決Session共享問題

ThreadLocal不是一個線程的本地實現,即它不是一個線程,而是線程局部變量(Thread Local Variable)。它的作用是為每一個使用這個變量的的線程都提供一個變量值的副本,並且每一個線程都可以獨立地改變自己的副本,而不會和其他線程的副本沖突,從線程的角度來看,就好像每一個線程都完全擁有一個該變量一樣。

ThreadLocal會給每一個線程提供一個變量的副本,就可以實現線程范圍內Session共享,從而避免線程頻繁創建和銷毀Session,但是需要注意,使用完畢後需要手動關閉。

package com.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class LoginDao {
	private Session session=null;
	private Transaction tran=null;
	private static final ThreadLocal<Session> s=new ThreadLocal<Session>();//使用ThreadLocal方式來管理Session
	
	public LoginDao(){
		Configuration config=new Configuration().configure();
		SessionFactory factory=config.buildSessionFactory();
		//this.session=factory.openSession();
		this.session=s.get();//調用ThreadLocal的get方法得到session
		if (session==null) {
			this.session=factory.openSession();
			//this.session=factory.getCurrentSession();//使用這種方法,需要在配置文件中添加相應的配置信息
			s.set(session);//將session 放到ThreadLocal用進行管理
		}
	}
	
	/**
	 * 插入數據
	 */
	public void save(Login login){
		try {
			tran=session.beginTransaction();
			this.session.save(login);
			//提交事物
			tran.commit();
			System.out.println("用戶信息保存成功");
		} catch (RuntimeException e) {
			if (tran!=null) {
				tran.rollback();
				//throw e;
				e.printStackTrace();
			}
		}finally{
			this.session.close();
		}
	}
	/**
	 * 更新操作
	 */
	public void update (Login login){
		try {
			tran=session.beginTransaction();
			session.update(login);
			tran.commit();
			System.out.println("更新成功");
		} catch (HibernateException e) {
			if (tran!=null) {
				tran.rollback();
				//throw e;
				e.printStackTrace();
			}
		}finally{
			this.session.close();
		}
	}
	/**
	 * 刪除操作
	 * @param login
	 */
	public void delete(Login login){
		try {
			tran=this.session.beginTransaction();
			session.delete(login);
			tran.commit();
			System.out.println("刪除成功");
		} catch (HibernateException e) {
			if (tran!=null) {
				tran.rollback();
				//throw e;
				e.printStackTrace();
			}
		}finally{
			this.session.close();
		}
	}
	/**
	 * 根據主鍵精確查詢
	 * 
	 */
	public Login getLoginByid(String name){
		Login login=null;
		String hql="from Login as l where l.username=?";
		Query query=this.session.createQuery(hql);
		query.setString(0, name);
		Iterator list=query.list().iterator();
		if (list.hasNext()) {
			 login=(Login)list.next();
		}
		System.out.println("主鍵精確查詢");
		this.session.close();
		return login;
	}
	
	public List queryAll(){
		List list=null;
		String hql="from Login as l";
		Query query =this.session.createQuery(hql);
		list=query.list();
		System.out.println("查詢所有記錄");
		this.session.close();
		return list;
	}
	/**
	 * 根據用戶名進行模糊查詢的操作
	 */
	public List queryLike(String name){
		
		List list=null;
		String hql="from Login l where l.username like ?";
		Query query =this.session.createQuery(hql);
		query.setString(0, "%"+name+"%");
		list=query.list();
		System.out.println("模糊查詢");
		this.session.close();
		return list;
	}

}

3.2、openSession()和getCurrentSession()解析

Hibernate的SessionFactory類除了提供openSession()來返回Session外,還提供了getCurrentSession()方法,此方法是Hibernate的3.0.1版本之後才增加的,通過這個方法同樣可以得到一個Session,但是這兩個方法之間還是有區別的,它們之間的區別如下:

1.getCurrentSession()創建的Session會綁定當當前線程,而openSession()不會。

2.getCurrentSession()創建的Session會在事物回滾或事物提交後自動關閉,而openSession()創建的必須手動關閉,(調用的Session的close()方法)

注意:

(1).當使用本地事務(jdbc事務)時,需要在Hibernate.cfg.xml文件的<session-factory>節點中添加如下代碼:

<property name="hibernate.current_session_context_class">thread</property>

(2).當使用的是全局事務(JTA事務)時,需要在hibernate.cfg.xml文件的<session-factory>節點中添加如下代碼:

<property name="hibernate.current_session_context_class">jta</property>

如果使用getCurrentSession()方法,而沒有在配置文件中添加以上的這些內容,那麼編譯不會報錯,但是在運行程序時會出錯,“No CurrentSessionContext configured!”,另外由於使用getCurrentSession()方法不需要手動關閉Session,所以不需要調用Session的close()方法。

3.3、Session的使用

3.3.1、save()方法

Session的Save()方法使一個自由對象(也稱臨時對象)轉變為持久對象。調用Session的save()方法需要完成3件事:

1.把對象加入Session的緩存中,使它進入持久化狀態。

2.選用映射文件指定的標識符生成器,為持久化對象分配唯一的OID.

3.計劃執行一個insert語句,把對象當前的屬性值裝到insert語句中。

需要注意的是在save()方法後,在事務commit()方法之前,又修改了持久化對象的屬性,哪個當session在清理的時候,會額外執行一個SQL update操作。

User user = new User();
user.setPassword("123");
user.serUsername("xiazhongwei");
Session session = sessionFactory.openSession();
Transaction tran = session.beanTransaction();
session.save(user);
user.setPassword("456");
tran.commit();
session.close();

  第一條:inser into USER (ID ,USERNAME,PASSWORD) values(1,"xiazhongwei","123");

第二條: update USER SET USERNAME="xiazhongwei",PASSWORD="456" where id=?

3.3.2、persist()方法

 persist()方法與save()方法作用類似,也能把一個自由對象轉變為持久對象。

需要注意persist()方法是在hibernate3中才出現的它實現了EJB3規范中定義的持久化語義,當調用persist()方法時,並不一定會立即為持久化對象的OID賦值,而有可能在Session清理的時候才為oid賦值。另外咋事務邊界以外調用persist()方法,這個方法不會計劃執行一個insert語句。。

3.3.3、update()方法

執行session的update方法使一個游離的對象變為持久對象,並計劃執行一條update語句。會完成一下操作:

1.把游離對象加入當前session的緩存中,使它變為持久化對象。

2.計劃執行一條update語句。

3.Session只有在清理緩存的時候才會執行update語句,及使多次修改對象的數據也只會在清理緩存的時候執行一次update語句。

3.3.4、saveOrUpdate()方法

如果傳入的是臨時對象,就調用save()方法,如果傳入的是游離對象,就調用update方法,而如果傳入的是持久化對象就直接返回。

3.3.5、load()方法

方法是根據給定的OID從數據庫中加載一個持久化對象。load()方法當數據庫中不存在與oid對應的記錄時,load()方法跑出org.hibernate.ObjectNotFoundException異常。

3.3.6、get()方法

get()方法和load()方法相似,都是使用oid檢索持久化對象,get()方法當數據庫中不存在與oid對應的記錄時,get()方法返回null.

和load()方法的還有一個區別是兩者采用了不同的檢索策略,在默認情況下所有的持久化對象都使用延遲加載策略,<class name="com.entity.User" table="USER" lazy="true">如果不加lazy屬性默認也是true,如果給lazy屬性改為false那麼load()方法就會立即加載。但是get()方法則忽略class元素的lazy屬性,也就是說不管lazy屬性寫的什麼值,get()方法都會采用立即加載的策略。

那麼何時該使用load何時該使用get呢?

(1).如果加載一個對象的目的是為了訪問它的各個屬性,那麼可以使用get()方法。

(2).如果加載一個對象是為了刪除它或者簡歷與別的對象的關聯關系,可以用load()方法。

3.3.7、delete()方法

delete()方法即可以刪除持久對象,也可以刪除游離對象,當調用delete()方法時,如果傳入的參數是游離對象,會先使游離對象與當前session關聯,使游離對象變為持久對象,,而如果參數傳入的是持久對象的時候,則會忽略這一步。

delete()方法也是在session清理緩存的時候執行一條delete語句。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved