博客信息

hibernate之加载策略

发布时间:『 2019-02-26 05:43』  博客类别:SSH  阅读(756)

1、hibernate对象状态简介

图解如下

 

临时态:刚创建出来的对象/被删除的对象

持久态:从数据库读取出来的对象/new出来的对象保存到数据库后。一级缓存存放着对象的快照
游离态:一级缓存中可能存在可能不存在的对象

一级缓存:被称为session级别的缓存,session代表着一次会话,一次数据库的操作。里面放着被操作的对象的快照(持久化对象)

 

好比:陌生人借钱,好盆友借钱、多年未曾练习的好盆友借钱。

 

2、一级缓存、快照、orm特性

代码

public void edit(Student student) {

Session session = SessionFactoryUtils.openSession();

Transaction transaction = session.beginTransaction();

Student s = (Student) session.get(Student.class, student.getSid());

if (null != s) {

if (!s.getVersion().equals(student.getVersion())) {

throw new RuntimeException("对象已过期或不存在");

}

s.setSname(student.getSname());

}

// session.update(student);

transaction.commit();

SessionFactoryUtils.closeSession();

}

 

测试

@Test

public void testEditStudent() {

student.setSid(1);

// student.setVersion(2);

student.setSname("zs23");

dao.edit(student);

}

 

控制台结果如下:

我们会发现,在代码中并没有调用session.update方法,控制台依然出现了update语句。

那是因为通过session.get方法得到的对象,本身处于持久化状态。对象发生改变,hibernate管理该对象,会自动将改变后的对象持久化到数据库中。

 

3、加载策略

立即加载:通过调用session方法,马上产生出对应的sql语句进行查询。比如get方法

延迟加载:hibernate保留oid,当需要用到该对象,再产生sql语句进行查询,比如load方法。

 

Get代码如下

public Student get(Student student) {

Session session = SessionFactoryUtils.openSession();

Transaction transaction = session.beginTransaction();

Student s = (Student) session.get(Student.class, student.getSid());

System.out.println(s);

transaction.commit();

SessionFactoryUtils.closeSession();

return s;

}

 

测试:

@Test

public void testGet() {

student.setSid(1);

Student s = dao.get(student);

System.out.println(s);

 

}

 

控制台:

小李飞刀_hibernate


Load
代码如下 

public Student load(Student student) {

Session session = SessionFactoryUtils.openSession();

Transaction transaction = session.beginTransaction();

System.out.println(123);

Student s = (Student) session.load(Student.class, student.getSid());

System.out.println(456);

// System.out.println(s);

transaction.commit();

SessionFactoryUtils.closeSession();

return s;

}

 

测试代码如下:

@Test

public void testLoad() {

student.setSid(1);

Student s = dao.load(student);

System.out.println(s.getSid());

System.out.println(s.getSname());

}

控制台

小李飞刀_hibernate 

报错原因:执行load方法,session中只保留对象的oid,当要使用查询出来的对象的时候,hibernate才会生成sql语句并且执行。测试代码中,使用该对象的时候,session已经关闭,所以junit报错。

 

4、并发控制

*.hbm.xml中指定版本控制字段

小李飞刀_hibernate


第一次新增,默认版本号为
0. 

 

执行修改方法代码

@Test

public void testEditStudent() {

student.setSid(2);

// student.setVersion(2);

student.setSname("zs23");

dao.edit(student);

}

控制台打印

小李飞刀_hibernate


当两个用户同时对一条数据进行操作的时候,那么会出现并发问题。
Hibernate提供的version标签很好的解决这一问题。我们在编码的时候也可以沿用这一思想。结论:除了oid以及version版本控制字段其他字段发生改变,那么数据库执行update sql语句。版本号+1.

举个例子:

张三、李四同时对version=1的一条数据进行update操作。张三先提交,那么数据库的数据version=2,李四后提交,但是提交时的数据version=1,与数据库的version匹配不上,这是修改就不会成功。会抛出版本异常。

关键字:     hibernate  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有