2014-09-22 66 views
0

给出的定义(为了简化省略IDS):在setter调用之后Hibernate是否会触发更新查询?

@Entity 
class A { 
    @OneToMany(mappedBy="a", cascade=CascadeType.ALL) 
    B b; 
} 

@Entity  
class B { 
    @ManyToOne 
    @JoinColumn(nullable=false) 
    A a; 
} 

而且声明:

a.setB(b); 
b.setA(a); 
session.update(a); 
session.flush(); 

我们得到PropertyValueException在冲洗( “非空属性引用null或瞬时值”) 。但是,如果我们将“a.setB(b)”替换为“b.setA(a)”,则不会引发异常。就好像“a.setB(b)”在“b.a”中使用null值触发sql更新,而不管下一个setter和update行如何。

我们之前没有收到过这种行为,它显然是从hibernate v3.6迁移到v4.3后开始的。 hibernate如何决定根据实体和会话中的实体状态更改或方法调用来生成sql更新?有没有可以设置的配置将其更改为以前的行为?

注意:这些语句被简化了,它们之间有更多的代码。

+0

有一些自动刷新设置...我现在不记得,但每个DML查询后,我一直在做齐平。 – 2014-09-22 13:25:59

+0

我的flushMode是AUTO。我试着改为COMMIT,但问题仍然存在。 – Vituel 2014-09-22 19:21:22

+0

其实我已经在web.xml(http://stackoverflow.com/a/13362558/2004857)里面的“openSessionInViewFilter”中设置了flushMode,它没有工作。这一次,我在sessionFactory.getCurrentSession()之后以编程方式做了它,并且异常没有抛出。 – Vituel 2014-09-22 21:25:06

回答

0

我觉得你得到这个是因为“或瞬态价值”。确保你从数据库或者你告诉Hibernate来保存它,以及(或者与到persist()/update()的显式调用)或通过创建级联关系

0

Hibernate不会触发一个查询正确端来一B实例在二传手之后,但在冲过之后。

在我的情况下,在“a.setB(b)”(而实体处于不一致的状态:b.a == null)之后,读操作正在触发flush操作,因为我在hibernate中将flushMode设置为AUTO。

我有固定它的方式有两种:

  1. 移动读操作后“b.setA(一)”,当国家是一致的; 或
  2. 将flushMode设置为COMMIT。 Note that you now have to manually flush before every db operation involving entities updated earlier in the same transaction or you might get stale data.

    Session session = sessionFactory.getCurrentSession(); 
    session.setFlushMode(FlushMode.COMMIT); 
    
+1

我想了解你是如何解决这个问题的,A和B之间有什么样的关系?它是一对一吗?在你的回答中''find'是什么意思'在我的情况下,flush是由一个find后触发的''并且'将find移到后面'和'注意你现在必须在每次find之前手动刷新' ?因为在hibernate会话界面中没有find方法。在这种情况下,陈旧的数据如何产生?你能否详细说明一下。 – Chaitanya 2014-09-23 05:09:03

+0

你是完全正确的。我已经添加了定义关系的注释,现在它会更有意义。通过“查找”我的意思是“读取操作”。关于flushMode和陈旧的数据,我认为这解释得很好:http://stackoverflow.com/a/7222097/2004857。 感谢您指出这些事情。 – Vituel 2014-09-23 12:32:14

相关问题