图解如下:
临时态:刚创建出来的对象/被删除的对象
持久态:从数据库读取出来的对象/new出来的对象保存到数据库后。一级缓存存放着对象的快照
游离态:一级缓存中可能存在可能不存在的对象
一级缓存:被称为session级别的缓存,session代表着一次会话,一次数据库的操作。里面放着被操作的对象的快照(持久化对象)
好比:陌生人借钱,好盆友借钱、多年未曾练习的好盆友借钱。
代码
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管理该对象,会自动将改变后的对象持久化到数据库中。
立即加载:通过调用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);
} |
控制台:
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()); } |
控制台
|
报错原因:执行load方法,session中只保留对象的oid,当要使用查询出来的对象的时候,hibernate才会生成sql语句并且执行。测试代码中,使用该对象的时候,session已经关闭,所以junit报错。
在*.hbm.xml中指定版本控制字段
第一次新增,默认版本号为0.
执行修改方法代码
@Test public void testEditStudent() { student.setSid(2); // student.setVersion(2); student.setSname("zs23"); dao.edit(student); } |
控制台打印
当两个用户同时对一条数据进行操作的时候,那么会出现并发问题。Hibernate提供的version标签很好的解决这一问题。我们在编码的时候也可以沿用这一思想。结论:除了oid以及version版本控制字段其他字段发生改变,那么数据库执行update sql语句。版本号+1.
举个例子:
张三、李四同时对version=1的一条数据进行update操作。张三先提交,那么数据库的数据version=2,李四后提交,但是提交时的数据version=1,与数据库的version匹配不上,这是修改就不会成功。会抛出版本异常。
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有