Leo*_*Leo 0 java persistence hibernate
我试图了解Hibernate中不同的对象状态.我尝试了以下操作,无法找到所显示行为的解释.有人可以帮忙吗?
以下是我要做的事情:在Employee表中插入一条新记录(empId是主键).在同一事务中,更新新添加的记录(使用查询,修改empName).然后当我检查持久对象的empName属性时,它继续显示旧的empName值.作为一个持久对象,我希望它能反映数据库中所做的更改.我不明白为什么没有.(我的hibernate配置文件已将所有设置为默认值,但"hibernate.hbm2ddl.auto"属性设置为更新)但是,在执行更新后,当我使用getEmpName返回的值设置持久对象的empName时(显示为旧的)由sysout表示的empName值,表中的最终数据显示了新的empName值(即我使用hql更新的值).请参考以下代码:
Transaction tx = session.getTransaction();
tx.begin();
Employee e1 = new Employee();
e1.setEmpId(1);
e1.setEmpName("Jack");
e1.setEmpAge(25);
session.save(e1);
System.out.println("before: "+e1.getEmpName()); //prints Jack
session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();
System.out.println("after: "+e1.getEmpName()); //prints Jack
e1.setEmpName(e1.getEmpName()); //should update database
tx.commit(); //sets empName value to Jack_new, as seen in table
System.out.println("last: "+e1.getEmpName()); //prints Jack
Run Code Online (Sandbox Code Playgroud)
直接在数据库中操作数据(使用SQL数据操作语言(DML)语句:INSERT,UPDATE,DELETE)不会影响内存状态.
当您使用以下直接DML进行更新时,
session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();
Run Code Online (Sandbox Code Playgroud)
它将绕过Hibernate持久化上下文(以及所有缓存).因此,虽然实际上empName是Jack_new在DB中更新,但它在持久化上下文中的实例仍保留旧值.
您可以使用从底层数据库session.refresh(e1);重新读取的值,以便刷新.e1e1.empNameJack_new
通常,我们不会手动编写UPDATE语句来执行update.将更新的值设置为持久化实例的属性.在刷新期间,hibernate将执行脏检查,自动生成并发出相应的更新SQL以更新这些脏实例.
(回复评论):
然而,只是在做tx.commit()我设置e1.empName旧值之前(即价值被e1.getEmpName()返回).不过在数据库中看到的终值是新的价值?
/**e1 become persisted after save()**/
session.save(e1);
/**e1.empName is updated to new value in the DB , but as the direct DML
will not affect in-memory state , e1.empName in the java side
still keeps the old value***/
session.createQuery("update Employee set empName = \'Jack_new\' where id=1").executeUpdate();
/** As you only set `e1.empName` to its original value , the values of `e1` do
not have any changes. Thus , during the flushing (which occurs at the moment
before `commit()`) , hibernate will consider that `e1` is not dirty and
hence no update SQL will be generated and issued to update e1 .
***/
e1.setEmpName(e1.getEmpName());
Run Code Online (Sandbox Code Playgroud)
因此,结果是Jack_new保存在DB中.