问题描述
先看代码: public static void main(String[] args) throws Exception { Configuration cfg = new Configuration(); SessionFactory sf = cfg.configure().buildSessionFactory(); Session session = sf.openSession(); //session.setFlushMode(FlushMode.MANUAL); session.beginTransaction(); Parent p = new Parent(); p.setName("hello"); session.save(p); System.out.println(1); p.setName("world"); System.out.println(2); session.getTransaction().commit(); session.close(); }这是我的一段测试代码,Parent类除了id以外仅有一个name属性,我执行这段代码,在控制台的输出是这样的:Hibernate: insert into parent (name) values (?)12Hibernate: update parent set name=? where id=?我的疑问是,为什么save方法会在打印语句之前将sql语句发送到数据库,是立即执行的,update方法的行为可以理解,提交事务时才同步到数据库,我记得以前save方法也不会立即发送sql的,而是flush或者commit时才会,我用的hibernate是3.3.1.GA版本的,难道是这个原因吗?当我把session.setFlushMode(FlushMode.MANUAL)的注释去掉之后输出变成了这样:Hibernate: insert into parent (name) values (?)12因为没有手动显式调用flush,所有后来的update并没有发出,但是save仍然是立即同步的,不解啊!
解决方案
楼主可以看下,save方法返回一个Serializable标识,就是因为这个,所以他要立即执行insert语句,如果想要不执行的话,可以试一下persist方法,persist方法是把一个瞬态的实例持久化,但是并不保证标识符被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时间。这里说的表示就是save方法返回的标识,由于save方法必须立刻把标识填入持久化实例中,所以,它会立刻执行insert语句。不知道我说的楼主是否明白。希望对楼主有帮助
解决方案二:
这里补充下,如果用persist方法,不像insert立即执行,就要把这个方法的调用放到事务外,不管是save还是persist只要是放在事务里都会触发insert语句的立即执行。