所以在我的数据库中,我有3行,两行的defaultFlag为0,一行设置为1,现在在我的处理中,我将一个对象的defaultProperty从0更新为1,但我还没有保存这个对象。
在保存之前我需要查询数据库并查找是否有任何行设置了defaultFlag,只有1个默认设置。
所以在进行更新之前运行查询以查找是否设置了默认值并且我得到2个值,请注意这里如果我去检查db然后只有1行默认设置但查询给了我两个结果,因为这。对象默认属性已从0更改为1,但请注意,此对象尚未保存在数据库中。
我真的很困惑,为什么hibernate查询返回2时,如果在数据库中有一行默认设置,而其他对象的默认属性已更改但未保存。
任何想法都会有所帮助。如果需要,我可以提供查询。
更新
根据建议,我在运行查询之前添加了session.clear()。
session.clear();
String sql = "SELECT * FROM BANKACCOUNTS WHERE PARTYID = :partyId AND CURRENCYID = :currencySymbol AND ISDEFAULTBANKACCOUNT= :defaultbankAccount";
SQLQuery q = session.createSQLQuery(sql);
q.addEntity(BankAccount.class);
q.setParameter("partyId", partyId);
q.setParameter("currencySymbol", currencySymbol);
q.setParameter("defaultbankAccount", 1);
return q.uniqueResult();
并按预期返回结果中的1行但现在正在
嵌套异常是org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已经与会话异常相关联
答案 0 :(得分:3)
在开始更改之前查询哪一行设置了“默认标志”,或者使用默认标志设置&查询行的列表。除了你想要设置的那个之外,清除所有。
非常容易,停止使用您的“脆弱”当前方法,这种方法会在并发或数据处于不一致状态时中断。请改用可靠的方法,始终将数据设置为有效状态。
protected void makeAccountDefault (BankAccount acc) {
// find & clear any existing 'Default Accounts', other than specified.
//
String sql = "SELECT * FROM BANKACCOUNTS WHERE PARTYID = :partyId AND CURRENCYID = :currencySymbol AND ISDEFAULTBANKACCOUNT= :defaultbankAccount";
SQLQuery q = session.createSQLQuery(sql);
q.addEntity(BankAccount.class);
q.setParameter("partyId", partyId);
q.setParameter("currencySymbol", currencySymbol);
q.setParameter("defaultbankAccount", 1);
//
List<BackAccount> existingDefaults = q.list();
for (BankAccount existing : existingDefaults) {
if (! existing.equals( acc))
existing.setDefaultBankAccount( false);
}
// set the specified Account as Default.
acc.setDefaultBankAccount( true);
// done.
}
这就是你编写正确代码的方法,简单易懂。可靠。永远不要制定或依赖关于数据或内部状态可靠性的弱假设,请务必阅读&amp;在执行操作之前处理“事先状态”,只需实现代码清理&amp;对,它会很好地为你服务。
答案 1 :(得分:1)
我认为您的第二个查询根本不会被执行,因为该实体已经在第一级缓存中。
由于您的事务尚未提交,因此您无法在基础数据库中看到更改。
(这只是猜测)
答案 2 :(得分:0)
这只是猜测,因为你没有提供很多细节,但我想你在会话开放时执行了myObject.setMyDefaultProperty(1)
。
在这种情况下,请注意不需要实际执行session.update(myObject)
来保存更改。这是hibernate透明地完成数据库更新的标称情况。
所以,事实上,我认为您的更改已保存...(但当然没有提交,因此在您检入数据库时没有看到)
要验证这一点,您应该启用hibernate.show_sql选项。您将看到是否触发了Update语句(我建议始终在开发阶段启用此选项)