1. 程式人生 > >hibernate之載入策略

hibernate之載入策略

1. 物件(hibernate管理的物件)的三種狀態:臨時狀態、持久狀態、遊離狀態

 a、hibernate通過管理物件來操作資料庫,這裡物件指的是持久態的物件

b、各種狀態的物件是可以相互轉換

 

2、一級快取與快照 

一級快取又被成為session級別的快取,相當於資料庫中的某條資料在hibernate產生一個快照,並且將值封裝進物件裡,如果說物件發生了改變,那麼它會與之前的hibernate中的快照進行對比,如果不一致,那麼就會修改資料庫中的資料,以下程式碼可體現:

package com.zking.three.test;

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

import com.zking.one.entity.User;

public class Demo1 {

	public static void main(String[] args) {
		Configuration cfg=new Configuration().configure();
		SessionFactory sessionFactory=cfg.buildSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction transaction = session.beginTransaction();
		
		User user = session.get(User.class, 3);//根據ID將user查出來
		user.setUserName("小明");//給user重新賦一個name
				
		transaction.commit();//提交事務
		session.close();//關閉session
	}
}

執行後資料庫裡的資料就會發生改變

3. 載入策略

a、立即載入,即session的get方法

b、延遲載入(懶載入),懶載入就是將查詢的oid(object id)儲存到session的代理proxy中,當真正要用到查詢的物件時,再去執行查詢的SQL語句,即session的load方法

package com.zking.three.test;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.zking.one.entity.User;
import com.zking.two.entity.Student;
import com.zking.two.util.SessionFactoryUtil;

public class UserDao {

	/**
	 * 立即載入
	 * @author LJ
	 * @Date 2018年10月22日
	 * @Time 下午3:02:01
	 * @param user
	 * @return
	 */
	public User getUser(User user) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		User u = session.get(User.class, user.getId());
		transaction.commit();
		SessionFactoryUtil.closeSession();
		return u;
	}
	
	/**
	 * 懶載入(延時載入)
	 * @author LJ
	 * @Date 2018年10月22日
	 * @Time 下午2:57:14
	 * @param user
	 * @return
	 */
	public User loadUser(User user) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		User u = session.load(User.class, user.getId());
		transaction.commit();
		SessionFactoryUtil.closeSession();
		return u;
	}

        /**
	 * 併發修改例子所用
	 * @author LJ
	 * @Date 2018年10月23日
	 * @Time 下午1:44:58
	 * @param student
	 */
	public void updateStudent(Student student) {
		Session session = SessionFactoryUtil.getSession();
		Transaction transaction = session.beginTransaction();
		session.update(student);
		transaction.commit();
		SessionFactoryUtil.closeSession();
	}
}

測試立即載入:

        @Test
	public void testGetUser() {
		User user=new User();
		user.setId(3);
		User u = new UserDao().getUser(user);
		System.out.println(u.getUserName());
	}

效果:

測試懶載入:

        @Test
	public void testLoadUser() {
		User user=new User();
		user.setId(3);
		User u = new UserDao().loadUser(user);
		System.out.println(u.getUserName());
	}

效果:

報LazyInitializationException異常,是因為懶載入是當真正要用到查詢的物件時,再去執行查詢的SQL語句,但這時session已經關閉了,所以會出現異常

4、併發控制

業務場景:不同的兩個使用者同時對同一條資料進行修改,後提交的資訊會覆蓋先提交的資訊,針對這一現象,hibernate提供瞭解決方法,就是在資料庫裡和實體類里加一個version列段(資料庫裡該列段須為int型別,預設值為1),再在xml裡進行配置

注:配置時version屬性要放在property屬性的前面

 測試:

        @Test
	public void testUpdateStudent() {
		Student student=new Student();
		student.setSid(5);
		student.setVersion(2);
		student.setSname("劉備");
		new UserDao().updateStudent(student);
	}

每一次修改成功後,資料庫裡version會自增1,若修改時version的值沒有與資料庫裡的對應則會報錯:ERROR: HHH000346: Error during managed flush [Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.zking.two.entity.Student#5]]