1. 程式人生 > >Hibernate:一級快取

Hibernate:一級快取

什麼是快取:

快取將資料庫/硬碟上檔案中資料,放入到快取中(就是記憶體中一塊空間).當再次使用的使用,可以直接從記憶體中獲取.

快取的好處:

提升程式執行的效率.快取技術是Hibernate的一個優化的手段.

Hibernate分成兩個基本的快取:

  • 一級快取:Session級別的快取.一級快取與session的生命週期一致.自帶的.不可解除安裝.

  • 二級快取:SessionFactory級別的快取.不是自帶的.

一級快取的生命週期和session的生命週期一致,當前sessioin一旦關閉,一級快取就消失,session間不能共享一級快取的資料,因此一級快取也叫session級的快取或事務級快取。一級快取只存實體物件的 ,它不會快取一般的物件屬性(查詢快取可以),即當獲得物件後,就將該物件的快取起來,如果在同一session中如果再去獲取這個物件時,它會先判斷快取中有沒有該物件的id,如果有就直接從快取中取出,反之則去資料庫中取,取的同時將該物件的快取起來.

圖解:

在這裡插入圖片描述

以下對hibernate的一級快取進行程式碼測試: 1.1:hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<!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>
 <!-- 1. 資料庫相關 -->
  <property name="connection.username">root</property>
  <property name="connection.password">123</property>
  <property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8</property>
  <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  <!-- 連線MySQL資料庫 -->
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
  <!-- 2.配置本地事務(No CurrentSessionContext configured!) -->
  <property name="hibernate.current_session_context_class">thread</property>
  
  <!-- 3. 除錯相關 -->
  <property name="show_sql">true</property>
  <property name="format_sql">true</property>
  
  <!-- 4.hibernate需要管理的資料庫表對應的實體類對映檔案 -->
  <mapping resource="com/zking/one/entity/User.hbm.xml"></mapping>
   </session-factory>
</hibernate-configuration>

1.2:實體類:User.java

public class User implements Serializable {
	private Integer id;
	private String userName;
 	private String userPwd;
	
	public User() {
	  super();
	 }
	 public Integer getId() {
	  return id;
	 }
	 public void setId(Integer id) {
	  this.id = id;
	 }
	 public String getUserName() {
	  return userName;
	 }
	 public void setUserName(String userName) {
	  this.userName = userName;
	 }
	 public String getUserPwd() {
	  return userPwd;
	 }
	 public void setUserPwd(String userPwd) {
	  this.userPwd = userPwd;
	 }
	 @Override
	 public String toString() {
	  return "User [id=" + id + ", userName=" + userName + ", userPwd=" + userPwd + ", realName=" + realName
	    + ", sex=" + sex + ", birthday=" + birthday + ", createDatetime=" + createDatetime + ", remark="
	    + remark + "]";
	 }
}

1.3:User.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
	   <class table="t_hibernate_user" name="com.zking.one.entity.User">
	      <id name="id" type="java.lang.Integer" column="id">
	       <generator class="increment"></generator>
	      </id>		
	     <property name="userName" type="java.lang.String" column="user_name"></property>
	     <property name="userPwd" type="java.lang.String" column="user_pwd"></property> 
	    </class>
   </hibernate-mapping>

1.4:測試方法:

public class Demo3 {
      Session  session= SessionFactoryUtils.getSession(); 
      Transaction transaction = session.beginTransaction();
      User user = session.get(User.class, 2);  // 馬上生成sql語句去查詢
      System.out.println(user.getRealName()); 
      User user = session.get(User.class, 2);  //不會發出sql,因為使用一級快取的資料
      System.out.println(user.getRealName());
      // 3.提交事務
      tx.commit();
      // 4.關閉資源
      session.close();
 }

1.5:深入理解一級快取中快照區:

public void demo4(){
     // 1.建立Session
     Session  session= SessionFactoryUtils.getSession(); 
     // 2.開啟事務
     Transaction transaction = session.beginTransaction();
     // 獲得一個持久態的物件.然後資料會分別放到一級快取區和一級快取快照區
     User user = session.get(User.class, 2);
     //user的名字改變了,一級快取和快照區資料不一致,事務提交的時候傳送SQL進行更新
     user.setRealName("是不是傻");
     // 3.提交事務
     tx.commit();
     // 4.關閉資源
    session.close();
}

結論:向一級快取存入資料的時候,放入一級快取區和一級快取快照區,當更新了一級快取的資料的時候,事務一旦提交,比對一級快取和快照區,如果資料一致,不更新,如果資料不一致,自動更新資料庫.