Hibernate查询没有返回正确的值

时间:2013-10-11 15:40:02

标签: java hibernate

所以在我的数据库中,我有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:具有相同标识符值的另一个对象已经与会话异常相关联

3 个答案:

答案 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语句(我建议始终在开发阶段启用此选项)