天天看點

hibernate的Session的saveOrUpdate等方法的使用

本文主要說的是Session的saveOrUpdate、clear、flush等方法的使用以及控制建表語句的輸出等。

1.Session的saveOrUpdate方法

先看下hibernate的API文檔的相關描述:

 void

saveOrUpdate(Object object)

          Either save() or update() the given instance, depending upon the value of its identifier property.

即根據Id判斷是調用save或者update方法,Id咋在資料庫不存在時調用save,Id在資料庫存在時調用update。

看下方法發的詳解

saveOrUpdate

public void saveOrUpdate(Object object)
                  throws HibernateException      
Either save() or update() the given instance, depending upon the value of its identifier property. By default the instance is always saved. This behaviour may be adjusted by specifying an unsaved-value attribute of the identifier property mapping. This operation cascades to associated instances if the association is mapped with cascade="save-update".
Parameters:

object

- a transient or detached instance containing new or updated state
Throws:

HibernateException

See Also:

save(java.lang.Object)

,

Session#update(Object object, Serializable id)

執行個體驗證

仍然使用之前的Techer

package com.baosight.model;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.SequenceGenerator;
import javax.persistence.TableGenerator;

/**
 * <p>Title: </p>
 * <p>Description:Teacher </p>
 * <p>Company: </p> 
 * @author yuan 
 * @date 2016-4-10 下午12:32:46*/
@Entity
@TableGenerator(name="tableGEN",table="table_gen",pkColumnName="pk_key",valueColumnName="pk_value",pkColumnValue="teacher",allocationSize=1)
@SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")
//@IdClass(value=TeacherPK.class)
public class Teacher {
	private String id;
	private String name;
	private String title;
//	private TeacherPK pk;
	@Id
	@GeneratedValue//auto
//	@GeneratedValue(strategy=GenerationType.TABLE,generator="tableGEN")
//	@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
//	@Id
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
//	@Column(updatable=false)
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
//	@EmbeddedId
//	@Id
	/*public TeacherPK getPk() {
		return pk;
	}
	public void setPk(TeacherPK pk) {
		this.pk = pk;
	}*/
	
}
           

使用JUnit測試

package com.baosight.model;

import static org.junit.Assert.*;

import javax.persistence.Column;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * <p>Title:TecherTest </p>
 * <p>Description:TODO </p>
 * <p>Company: </p> 
 * @author yuan 
 * @date 2016-4-13 下午10:32:17*/
public class TeacherTest {
	private static SessionFactory sf = null;
	@BeforeClass
	public static void beforeClass(){
		// 讀取配置檔案
		Configuration cfg = new AnnotationConfiguration();
		// 得到session工廠
		sf = cfg.configure().buildSessionFactory();
	}
	
	
	@Test
	public void testSaveOrUpdate() {
		// 教師測試類
		Teacher t = new Teacher();
		t.setName("t1");
		t.setTitle("中級");

		Session session = sf.getCurrentSession();
		// 開啟事務
		session.beginTransaction();
		// session執行
		session.saveOrUpdate(t);
		// 事務送出
		session.getTransaction().commit();
		
		t.setName("zhangsan");
		Session session1 = sf.getCurrentSession();
		// 開啟事務
		session1.beginTransaction();
		// session執行
		session1.saveOrUpdate(t);
		// 事務送出
		session1.getTransaction().commit();
		
		
	}
	@Test
	public void testClear() {
		//直接從資料庫查詢,會列印sql
		Session session = sf.getCurrentSession();
		// 開啟事務
		session.beginTransaction();
		// session執行
		Teacher t = (Teacher) session.get(Teacher.class, "1");
		System.out.println(t.getId());
		
		session.clear();
		
		Teacher t1 = (Teacher) session.get(Teacher.class, "1");
		System.out.println(t1.getId());
		System.out.println(t1==t);
		// 事務送出
		session.getTransaction().commit();
	}
	@Test
	public void testFlush() {
			//直接從資料庫查詢,會列印sql
			Session session = sf.getCurrentSession();
			// 開啟事務
			session.beginTransaction();
			// session執行
			Teacher t = (Teacher) session.load(Teacher.class, "1");
			t.setName("tttt");
			session.flush();
			t.setName("lisi");
			session.getTransaction().commit();
		
		// session執行
		// 事務送出
	}
	@Test
	public void testSchemaExport() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
	}
	@AfterClass
	public static void afterClass(){
		// 關閉session工廠
		sf.close();
	}
}
           

調用testSaveOrUpdate,第一次調用saveOrUpdate是将transient并為persistent,使用save;第二次調用saveOrUpdate是将detached變為persistent,使用update。運作結果如下:

hibernate的Session的saveOrUpdate等方法的使用
hibernate的Session的saveOrUpdate等方法的使用

2.Session的clear方法

先看下hibernate的API的介紹

void

clear()

          Completely clear the session.

方法的詳解如下:

clear

public void clear()      
Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do not close open iterators or instances of ScrollableResults.

完全清除會話。驅逐所有加載的情況,取消所有挂起的儲存、更新和删除。不關scrollableresults開放疊代器或執行個體。

就是說調用clear方法會清除session已經存在的所有緩存的執行個體

使用JUnit進行測試

調用上面的testClear方法,不使用clear時發現隻做了一次查詢,結果如下:

hibernate的Session的saveOrUpdate等方法的使用

testClear使用clear之後,發現查詢了2次

hibernate的Session的saveOrUpdate等方法的使用

3.Session的flush方法

先看下hibernate的API的介紹

 void

flush()

          Force the Session to flush.

方法的詳細介紹

flush

public void flush()
           throws HibernateException      
Force the Session to flush. Must be called at the end of a unit of work, before commiting the transaction and closing the session ( Transaction.commit() calls this method). Flushing is the process of synchronising the underlying persistent store with persistable state held in memory.
Throws:

HibernateException

迫使session重新整理。必須在一個工作單元結束前被調用,交易和關閉會話(Transaction.commit()調用此方法)。flush是底層持久化存儲和記憶體中的持久化狀态的同步過程。

也就是說flush預設是在Transaction.commit()時被調用,可以通過調用Session的flush方法實作在Transaction.commit()之前就調用flush,實作資料的存儲和狀态的同步。

使用JUnit進行測試

調用上面的testFlush方法,當不使用flush時,隻會在Transaction.commit()時做一次修改,結果如下:

hibernate的Session的saveOrUpdate等方法的使用

testFlush使用flush後,後做2次修改

hibernate的Session的saveOrUpdate等方法的使用

4.關于使用SchemaExport輸出建表語句

hibernate的配置檔案hibernate.cfg.xml中可以配置hbm2ddl.auto,以實作控制建表等,具體配置如下:

<!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>
           

屬性值update可以換成create,這樣每次都會重建立表

當然,hibernate也可以通過代碼來實作這個過程,即使用SchemaExport

首先看下hibernate的API文檔

org.hibernate.tool.hbm2ddl

Class SchemaExport

java.lang.Object
  
        
hibernate的Session的saveOrUpdate等方法的使用
org.hibernate.tool.hbm2ddl.SchemaExport
public class SchemaExport extends Object

Commandline tool to export table schema to the database. This class may also be called from inside an application. 

指令行工具導出表的資料庫架構。這個類可以在應用程式中調用。

構造方法

SchemaExport(Configuration cfg)

          Create a schema exporter for the given Configuration

需要加載配置檔案,跟使用session時差不多

實作代碼見上面的testSchemaExport方法,具體如下:

@Test
	public void testSchemaExport() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
	}
           

主要使用的是create方法

 void

create(boolean script, boolean export)

          Run the schema creation script.

create

public void create(boolean script,
                   boolean export)      
Run the schema creation script.
Parameters:

script

- print the DDL to the console

export

- export the script to the database

第一個參數可以控制是否将DDL語句輸出到控制台

使用JUnit測試,調用上面的testSchemaExport方法,第一個參數為true時,結果如下:

hibernate的Session的saveOrUpdate等方法的使用

create的第一個參數為false時

hibernate的Session的saveOrUpdate等方法的使用

以上即為hibernate的除了正常的CRUD之外比較常見的方法,需要在實際的使用過程中仔細體會。