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]]

猜你喜欢

转载自blog.csdn.net/weixin_42687829/article/details/83305236