Session.evict()
作用:从session缓存(EntityEntries属性)中逐出该对象.
但是与commit同时使用,会抛出异常
session = HibernateUtils.getSession();
tx = session.beginTransaction();
User1 user = new User1();
user.setName("李四");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//利用Hibernate将实体类对象保存到数据库中
//因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理
//不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
session.save(user);
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。
tx.commit();
解决在逐出session缓存中的对象不抛出异常的方法:
在session.evict()之前进行显示的调用session.flush()方法就可以了。
//利用Hibernate将实体类对象保存到数据库中
//因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理
//不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
session.save(user);
//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false
session.flush();
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。
Session.clear()
作用:清空session缓存
Session.flush()
作用:将session的缓存中的数据与数据库同步
PS:执行sql语句,但是不会提交
当更新或者保存大批量数据的时候,可以每固定数量的时候,进行清理缓存,同时清除缓存:
for (int i = 0; i < 1000;i ++){
if (i /20 == 0) {
session.flush();
session.clear();
}
}
因为把大量的对象放到session缓存中会浪费大量的内容空间。
这里是LZ看网上看到的一些session基础的资料。
Session里的对象有三种状态
1、自由状态
2、持久化状态
3、游离状态
自由状态:new出来的类,未与session绑定
持久化状态:session的save,update,persist等操作之后的对象就会与session绑定,即 持久化
游离状态: session的evict该对象,则成为了游离状态
----------------------------------------------------咯咯咯咯咯咯---------------------------------------------------------------------------------------
2014-04-26:
今天自己在做SQLQuery测试的时候,忘记提交事务了,然后就又学到了东西!
public class Test {
public static void main(String[] args) throws IOException {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
VO vo = new VO();
vo.setName("那哈哈哈");
session.beginTransaction();
session.save(vo);
System.out.println(vo.getId());
session.getTransaction()
session.close();
sf.close();
}
}
感觉自己一直没学好session
之前的我在想,这个打印出来的肯定是0;(默认:0)
但是打印出来的是12(数据库里已经有11个数据)
ps:之前保存了一个数据进数据库,但是又想知道自动生成的主键编号,然后就执行各种查询才得到(且高并发的时候还不一定能得到正确的)
ps:原来session早就已经帮我实现了。。。
但是这个方法,我没有提交事务。
我查看了一下数据库,里面还是11个数据,但是vo能实现主键递增且与数据库同步。
我有点明白session.flush()所说的与数据库同步的意思了。
以前一直以为flush了,就保存进数据库了。其实事务不提交,就不会保存进数据库。
第二个例子:
public class Test {
public static void main(String[] args) throws IOException {
SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
SQLQuery query = session.createSQLQuery("update vo set name = '喀喀' where id = 2");
session.getTransaction().commit();
// query.executeUpdate();
session.close();
sf.close();
}
}
这里我用到了SQLQuery。但是我没有调用executeUpdate()方法
然后提交了事务。
数据库里的数据什么都没有改变
这个时候我在事务提交之后,再执行executeUpdate()方法
控制台打印出:
Hibernate: update vo set name = '喀喀' where id = 2
我本能的就觉得执行成功了。但是事实是数据库还是没有改变。
最后在事务未提交前执行就OK了。
学的时候,依样画葫芦就可以了,知道写begintransaction和commit之间就可以了。
但是一直是知其然不知其所以然。
今天算是弄懂了点。