天天看點

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

使用Hibernate的“3個準備,7個步驟”

使用環境:Eclipse,MySQL

準備1:導入Hibernate庫(jar包);MySQL驅動包;log4j日志包。

Add Library  -- User Library  --  next  --  new user library  --  命名為hibernateJars  --  Add External Jars  --  apply

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

準備2:添加配置檔案 --  hibernate.cfg.xml (放在src下)

<!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>
	<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">12345</property>
	<property name="show_sql">true</property>
	<mapping resource="org/hibernate/test/legacy/Simple.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
           

URL:Window -- Show View -- Other -- Data Management -- Data Source Explorer -- Open -- 右鍵new

選擇mysql後next

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

檢驗url是否正确

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

準備3:添加實體類和映射檔案(User.hbm.xml),通常放在一個目錄下。

實體類User:

package cn.hrbust.pojo;

import java.sql.Date;

public class User {
	private int id;
	private String name;
	private String gender;
	private int age;
	Date birthday;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}
           

在資料庫中建立表T_USER:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

映射檔案User.hbm.xml配置:

<?xml version="1.0"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="cn.hrbust.pojo.User" table="T_USER">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <property name="gender"/>
        <property name="age"/> 
        <property name="birthday"/>
    </class>
    
</hibernate-mapping>
           

改hibernate.cfg.xml裡的配置

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

七個步驟:

package cn.hrbust.dao;

import java.sql.Date;

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


import cn.hrbust.pojo.User;

public class manageUser {
	public static void main(String[] args) {
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("張三");
		u.setGender("男");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2001-1-1"));
		try {
			cfg =new Configuration().configure();
			sf=cfg.buildSessionFactory();
			session=sf.openSession();
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			session.close();
			sf.close();
		}
		
	}
}
           

運作結果:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

問題解決:

問題1:The word 'localhost' is not correctly spelled

工程中有下劃線并提示 The word is not correctly spelled 此問題是Eclipse校驗單詞拼寫造成,如果出在配置檔案中,一般會影響到程式的正常執行.

解決方法:

1、在Eclipse下的Window--Preference輸入spell

2、然後把第一個複選框“Enable spell checking“給去掉就可以了

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

Hibernate API簡介

Hibernate 核心接口:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

Configuration:

概述:Configuration 類負責管理Hibernate 的配置資訊。啟動Hibernate、建立SessionFactory對象。

1. Hibernate運作的底層配置資訊:資料庫的URL、使用者名、密碼、JDBC驅動類,資料庫Dialect,資料庫連接配接池等。

2. Hibernate對象關系映射檔案(*.hbm.xml)。

Hibernate配置的兩種方法:

1. 屬性檔案(hibernate.properties)。

調用代碼:Configuration cfg = new Configuration();

 2. XML檔案(hibernate.cfg.xml)。

調用代碼:Configuration cfg = new Configuration().configure();

Configrure()方法預設讀hibernate.cfg.xml 

<!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>
	<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
	<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
	<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate</property>
	<property name="hibernate.connection.username">root</property>
	<property name="hibernate.connection.password">12345</property>
	<property name="hibernate.current_session_context_class">thread</property>
	<!-- 保證每個讀寫線程有唯一的session執行個體 -->
	<property name="show_sql">true</property>
	<mapping resource="cn/hrbust/pojo/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
           

SessionFactory:

概述:應用程式從SessionFactory(會話工廠)裡獲得Session(會話)執行個體。它在多個應用線程間進行共享。

1. SessionFactory是線程安全的(Thread-Safe),可以讓多個執行線程同時存取SessionFactory而不會有資料共享的問題。

2. 會話工廠緩存了生成的SQL語句和Hibernate在運作時使用的映射中繼資料。

 3. 需要注意的是SessionFactory是重量級的,因為一 般情況下,一個項目通常隻需要一個SessionFactory就夠(單例模式),當需要操作多個資料庫時,可以為每個資料庫指定一個SessionFactory。

調用代碼:SessionFactory sessionFactory = cfg.buildSessionFactory();

Session(會話):

概述: Session接口負責執行被持久化對象的CRUD操作(CRUD的任務是完成與資料庫的交流)

1. Session也稱為持久化管理器,因為它是與持久化有關的操作接口。

2. Session不是線程安全的,應該避免多個線程共享同一個Session執行個體。

3. Session通過SessionFactory打開,在所有的工作完成後,需要關閉。

4. 保證在一個線程中僅存在一個Session執行個體

      1. getCurrentSession (Hibernate 3+)

           getCurrentSession方法,保證了線程中Session的唯一性;

           調用代碼: Session session = sessionFactory.getCurrentSession();

           使用getCurrentSession需要在配置檔案中加入

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

     2. 可以采用ThreadLocal的辦法. (Hibernate 2)

     3. 把Session對象放在方法内部定義.

Transaction(事務):

概述: Transaction接口負責事務相關的操作。

它将應用代碼從底層的事務實作中抽象出來——這可能是一個JDBC事務,一個JTA使用者事務或者甚至是一個公共對象請求代理結構(CORBA)——允許應用通過一組一緻的API控制事務邊界。這有助于保持Hibernate應用在不同類型的執行環境或容器中的可移植性。

調用代碼:Transaction tx = session.beginTransaction();

    tx.commit();   //送出事務

    …

    tx.rollback(); //復原事務

注:使用Hibernate進行操作時(增、删、改)必須顯示的調用Transaction(預設:autoCommit=false)。

Query:

概述: Query(查詢)接口允許你在資料庫上執行查詢并控制查詢如何執行。查詢語句使用HQL或者本地資料庫的SQL方言編寫。

調用代碼:Query query = session.createQuery(“from User”);

單态模式(靜态代碼塊):

package cn.hrbust.dao;

import org.hibernate.HibernateException;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
//SessionFactory單态模式
public class HibernateUtil {
	private static SessionFactory sf=null;
	private static Configuration cfg=null;
//	靜态代碼塊,在類加載的時候隻能執行一次
	static {
		try {
			cfg = new Configuration().configure();
			sf = cfg.buildSessionFactory();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static SessionFactory getSessionFactory() {
		return sf;
	}
	public static void closeSessionFactory(){
		sf.close();
	}
}
           

main:

public static void main(String[] args) {
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("李四");
		u.setGender("男");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2001-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

單元測試:

查詢使用者對象:

//查詢使用者對象
	public void testQuerySUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			Query query=session.createQuery("from User");
			List<User> users=query.list();
//			for(int i=0;i<users.size();i++)
//			{
//				User u =users.get(i);
//				System.out.println(u.getName()+" "+u.getAge());
//			}
			for(User u: users)
			{
				System.out.println(u.getName()+" "+u.getAge());
			}
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

結果:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

儲存使用者對象:

//儲存使用者對象
	public void testSavaUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("張三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			/*
			 * Query query=session.createNamedQuery("from User"); List users=(List)
			 * query.list();
			 */
			session.save(u);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           

結果:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

自動表生成:

ExportSchema.java:

package cn.hrbust.dao;

import java.util.EnumSet;

import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;

public class ExportSchema {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//服務注冊對象
		ServiceRegistry sr= new StandardServiceRegistryBuilder().configure().build();
		Metadata metadata =new MetadataSources(sr).buildMetadata();
		//建立Schema,表的對象,目的是根據資料生成表
		SchemaExport se=new SchemaExport();
		se.create(EnumSet.of(TargetType.DATABASE), metadata);	
	}

}
           

User.hbm.xml:

<?xml version="1.0"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="cn.hrbust.pojo.User" table="improve">
        <id name="id">
            <generator class="identity"/>
        </id>
        <property name="name" column="username"/>
        <property name="gender" column="sex"/>
        <property name="age" column="age"/> 
        <property name="birthday" column="borndate"/>
    </class>
    
</hibernate-mapping>
           

結果:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

問題:

1.WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

解決辦法:

在url的配置中加入?useSSL=false

    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hellohibernate?useSSL=false</property>

連結: [link](https://blog.csdn.net/qq_40662239/article/details/114532028).
           

2.不能自動建立表

解決辦法:

<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>

操作實體對象

對象的狀态

1.瞬時對象(Transient Objects):由new操作符建立,且尚未與Session 關聯的對象被認定為瞬時(Transient)的,不和資料庫的資料有任何關聯關系。瞬時(Transient)對象沒有被持久化到資料庫中,也不會被賦予持久化辨別(identifier)。

如果瞬時(Transient)對象在程式中沒有被引用,它會被垃圾回收器(garbage collector)銷毀。

由于此對象沒有納入Session的管理,那麼此時該對象的任何變化都不會發出SQL語句。

可以通過調用Session的持久方法(save(),saveOrUpdate()等)進行持久化操作時才會轉變為  持久對象  ,并擁有和資料庫記錄相同的id辨別。

2.持久對象(Persist Objects):持久(Persistent)對象在資料庫中有對應的記錄,并擁有一個持久化辨別(identifier)。

持久對象可能是剛被儲存的,或剛被加載的,無論哪一種,按定義,它存在于相關聯的Session作用範圍内。

它有持久化管理器Session統一管理,持久對象是在事務中進行操作的——Transaction執行個體執行commit()之後,與資料庫進行同步。當事務送出時,通過執行SQL的INSERT、UPDATE和DELETE語句把記憶體中的狀态同步到資料庫中。

持久化對象任何變化都會自動地發出SQL語句,也就是說該對象和資料庫是實時關聯(同步的)。

3.托管對象(Detached Objects):與持久(Persistent)對象關聯的Session被關閉後,對象就變為脫管(Detached)的。托管表示這個對象不能再與資料庫保持同步,它們不再受Session管理。

對脫管(Detached)對象的引用依然有效,對象可繼續被修改。脫管(Detached)對象如果重新關聯到某個新的Session上, 會再次轉變為持久(Persistent)的(在Detached期間的改動将被持久化到資料庫)。

本質和瞬時對象相同,都沒有納入Session管理,自身的狀态變化,不會自動地發出SQL語句,差別:

 在資料庫中有與之對應的記錄

 比瞬時對象多了一個資料庫辨別id

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

Session的緩存

每個Session執行個體可以看作為一個容器,具有緩存,每一個持久化對象都被納入Session的緩存中。

資料庫中的一條記錄在一個Session中隻能對應一個對象,不同的Session可以有不同的對象對應資料庫中的同一個記錄。

Session有如下兩個作用:

1.充當蓄水池的作用,減少程式通路資料庫的次數。

2.保證緩存中的資料與資料庫同步。緩存畢竟不是資料庫,它的資料有可能和資料庫不一緻,這時Hibernate會負責将緩存中的資料同步到資料庫。

Session接口操縱實體對象的方法

 save()方法:把Java對象儲存資料庫中,把一個瞬時對象變成持久對象 。

//儲存瞬時使用者對象
	public void testSavaUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("張三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		//u此時是瞬時對象,沒有對象id,沒有納入session管理,不發sql語句
		u.setName("b");
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			session.save(u);
			//u:持久對象有對象id納入session管理自動發sql語句
			u.setName("a");//屬性改變持久化對象的屬性改變發update語句
			ts.commit();
			u.setName("a");//事務送出後,session關閉,屬性改變,持久化對象的屬性改變不會發update語句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

update()方法:更新資料庫中的Java對象,把一個托管對象變成持久對象 。

//托管對象
	public void testDetachedObject(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u=new User();
		u.setName("張三");
		u.setGender("女");
		u.setAge(21);
		u.setBirthday(Date.valueOf("2002-1-1"));
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			session.save(u);
			ts.commit();
			//在送出之後不執行,u為托管對象,有id,record,但是沒有session管理,不發sql語句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		//u: 此時是托管對象,沒有session,有id,有record,不自動發SQL語句
		u.setName("趙三");
		u.setAge(100);
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			session.update(u);
			//session.saveOrUpdate(u);
			ts.commit();
			//在送出之後不執行,u為托管對象,有id,record,但是沒有session管理,不發sql語句
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

delete()方法:把Java對象從資料庫中删除,把一個持久對象變成臨時對象 。

//删除使用者
	public void testDeleteUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			User u=session.get(User.class, 3);
			//持久化對象
			System.out.println(u.getName()+" "+u.getAge());
			//先get再進行其他操作
			session.delete(u);
			//瞬時對象,準确來說是删除對象
			u.setName("c");
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

load()/get()方法:根據對象辨別從資料庫中加載Java對象,傳回的對象都是處于持久化狀态。

get()方法:

//查詢一個對象
	public void testGetUser(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			User u=new User();
			u=session.get(User.class, 5);
			//get後是持久化對象
			System.out.println(u.getName()+" "+u.getAge());
			u.setName("老李");
			u.setAge(66);
			ts.commit();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

saveOrUpdate()方法同時包含了save() 和 update() 兩個功能:

1.如果傳入的參數是瞬時對象,就調用save()方法。

2.如果傳入的對象是托管對象,就調用update()方法。

close()方法,session緩存被清空,緩存中的所有持久化對象都變為遊離狀态。

evict(): 能夠從緩存中删除一個持久化對象,使它變為托管狀态。

clear():清除Session中所有緩存對象。

Session的update方法

使一個托管對象轉變成持久化對象,重新加入到緩存中。

調用update()方法時,并不立即發送SQL語句,對對象的更新操作将累積起來,在事務送出時,發送一條SQL語句完成全部的更新操作。

使一個托管對象轉變成持久化對象,重新加入到緩存中。

class的select-before-update屬性;如果想要session僅僅在對象的屬性發生變化的時候才執行update,可以把這個屬性設定為true。

用于偶爾更改的類,可以用一條select語句防止一條update語句的生成;對于經常更改的類,在每次update語句之前總是要發送一條多餘的select語句,反而影響性能。

删除對象——delete

Session的delete方法能夠是一個持久化對象或托管對象轉變為瞬時狀态

對于托管對象,delete方法從資料庫中删除與它對應的記錄;對于持久化對象,delete方法從資料庫中删除與它對應的記錄,并把它從session緩存中删除。

裝載對象——get 方法 和 load 方法的差別

Session的load()方法和get()方法都能夠根據給定的OID(Object ID對象唯一标示符)從資料庫中加載一個持久化對象到Session緩存中。

如果沒有符合條件的紀錄,get傳回一個null,load會抛出一個ObjectNotFoundException。

get:

當對象存在時:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

當對象不存在時:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

使用get方法時可以先判斷一下對象是否存在

load:

當對象存在時:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

當對象不存在時:

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

get方法立即加載對象, load傳回一個代理對象,延遲裝載對象,隻有在對象第一次被應用程式通路時,Hibernate才會從資料庫中加載該對象。

在無法确認持久對象是否存在于資料庫中時,開發者應當使用get()方法來擷取持久對象,通過判斷傳回值時候為null來确認持久對象的存在與否。

load、get方法或其它查詢方法傳回的對象都在session的緩存中。是以如修改對象的屬性,那麼事務送出後,會将資料同步到資料庫。

持久化對象必須唯一

一個Session中不能同時存在兩個ID相同的持久化對象

例如:id為userId的user_1對象已經存在Session中,這時如果Session中試圖産生一個user_2對象!!

Transaction tx = session.beginTransaction();

User user_1 = (User)session.get(User.class,6);

User user_2 = new User();

user_2.setId(6);

user_2.setUsername("李小四");

session.update(user_2);

最後将會産生異常:net.sf.hibernate.NonUniqueObjectException:

a different object with the same identifier value was already associated with the session

解決辦法:再将user_2變為持久化對象之前, 使用evict ()方法将user_1執行個體從session中去除。session.evict(user_1);

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

session.evict(u);後

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

與資料庫的同步

髒資料:資料僅僅在記憶體中更新而沒有同步到資料庫中稱為髒資料。

hibernate會監測髒資料,在盡可能遲的時候做同步的動作。(transparent transaction-level write-behind)

hibernate可以做到僅僅更新有變動的屬性,但是需要在映射檔案中設定dynamic-update=“true”,預設是false。這個功能用手工很難完成。

預設更新:更新所有屬性

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

設定dynamic-update="true"後

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

對象識别

對資料庫而言,其識别一條記錄唯一性的方式是根據主鍵值,如果手上有兩條記錄,它們擁有同樣的主鍵值,則它們在資料庫中代表同一個字段的記錄。

對Java而言,要識别兩個對象是否為同一個對象有兩種方式

記憶體位址識别(“= =”号識别)

根據equals()、hasCode()中的定義

 (預設Object類中定義的equals(Object o)方法也是按記憶體位址來比較的),源碼如下:

public boolean equals(Object obj){

        return  (this==obj);

  }

先探讨第一種Java的識别方式在Hibernate中該注意的地方,在Hibernate中,如果是在同一個session中根據相同查詢所得到的相同記錄,則它們會擁有相同的Java識别

舉個實際的例子:

Session session = sessions.openSession();

Person p1 = (Person)session.get(Person.class,1);

Person p2 =(Person)session.get(Person.class,1);

session.close(); 

System.out.println(p1 = = p2);

上面這個程式片段将會顯示true的結果,表示p1與p2是參考至同一對象

如果是以下的情況則會顯示false:

Session session1 = sessions.openSession();

Person p1 = (Person)session.get(Person.class,1);

session1.close(); 

Session session2 = sessions.openSession();

Person p2 = (Person)session.get(Person.class,1);

session2.close(); 

System.out.println(p1 == p2);

使用==來比較兩個對象的記錄是否代表資料庫中的同一條記錄是不可行的。如果您要有必要比較通過查詢後兩個對象的内容是否相同,必須重寫 equals()與hashCode()。

重寫方法之一,equals()與hashCode()的方法是根據資料庫的identity,就是透過getId()方法取得對象的id值并加以比較

例子中假設id的類型是String:

public class Person {   

           ....  

           public boolean equals(Object o) {       

                      if(this == o)

                            return true;      

                      if(id == null || !(o instanceof Person))

                            return false;        

                      final Person person== (Person) o;       

                            return this.id.equals(person.getId());   

}

public int hashCode() {        

return id == null ? System.identityHashCode(this):id.hashcode();   

} 

}
           

然而上面的例子是個不被鼓勵的例子,因為當一個對象被new出來而還沒有save()時,它并不會被賦予id值,這時候就不适用這個方法。

另一個比較被采用的方法是根據對象中真正包括的屬性值來作比較

public class Person {    
 ...    
public boolean equals(Object other) {        
if (this == other) return true;        
if (!(other instanceof Person)) 
	return false;         
final Person Person = (Person) other;         
if (! getUsername().equals(Person.getName())) 
	return false;        
if (!getBirthday().equals(Person.getBirthday())) 
	return false;
if (!getBirthday().equals(Person.getBirthday())) 
     return false;        
return true;    
}     
public int hashCode() {        
int result;        
result = getUsername ().hashCode();        
result = 29 * result + getBirthday().hashCode();      
return result;    
} 
}
           

String對象識别

//String對象識别
	public void testStringObjectIdentify(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			String a="abc";
			String b="abc";
			System.out.println(a==b);
			System.out.println(a.equals(b));
			String c="mnp";
			String d=new String("mnp");
			System.out.println(c==d);
			System.out.println(c.equals(d));
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

User對象識别

//User對象識别
	public void testUserObjectIdentify(){
		Configuration cfg =null;
		SessionFactory sf=null;
		Session session=null;
		Transaction ts=null;
		User u1=null,u2=null;
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			u1 =session.get(User.class,5);
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		try {
			sf=HibernateUtil.getSessionFactory();//SessionFactory單态模式
			session=sf.getCurrentSession();//保證每個讀寫線程有唯一的session執行個體
			ts=session.beginTransaction();
			u2 =session.get(User.class,5);
			ts.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			if(ts !=null) {
				ts.rollback();
			}
		}finally {
			//session.close();
			//sf.close();
		}
		try {
			System.out.println(u1==u2);//同一個session,引用相同
			System.out.println(u1.equals(u2));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
           
Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别

重寫hashcode:

public int hashCode() {     
		int result;
		result =getName().hashCode();
		result =29*result + getBirthday().hashCode();
		result =29*result + getAge();
		return result;    }
           

重寫equals方法後(在User.java中):

public boolean equals(Object obj) {        
	  if(this == obj) 
	  		return true;       
	  if(obj == null) 
	  		return false;        
	  if(!(obj instanceof User)) 
	  	return false;
	  User other = (User)obj;
	  if(id != other.id)
		  return false;
	  if(age != other.age)
		  return false;
	  if(!name.equals(other.name))
		  return false;
	  if(gender!=null && other.gender!=null) {
		  if(!gender.equals(other.gender))
			  return false;
	  }
	  if(!birthday.equals(other.birthday))
		  return false;
		  return true;
	  }  
           

User對象識别

Hibernate使用Hibernate的“3個準備,7個步驟”Hibernate API簡介操作實體對象對象識别