2

所以在我的数据库中,我有 3 行,两行的 defaultFlag 为 0,其中一个设置为 1,现在在我的处理中,我正在将一个对象的 defaultProperty 从 0 更新为 1,但还没有保存这个对象。

在保存之前,我需要查询数据库并查找是否有任何行设置了 defaultFlag,只有 1 个默认设置。

所以在更新之前运行查询以查找是否设置了默认值并且我得到了 2 个值,请注意,如果我去检查数据库,那么只有 1 行具有默认设置,但查询给了我两个结果,因为 this.object 默认属性已从 0 更改为 1,但请注意此对象尚未保存在数据库中。

我真的很困惑,为什么当数据库中有一行设置了默认值,而其他对象的默认属性已更改但未保存时,为什么休眠查询返回 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:具有相同标识符值的不同对象已与会话异常相关联

4

3 回答 3

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.
}

这就是您编写正确代码的方式,使其简单可靠。永远不要对数据或内部状态的可靠性做出或依赖薄弱的假设,在执行操作之前始终阅读和处理“预先状态” ,只需干净且正确地实现代码,它将为您提供良好的服务。

于 2013-10-11T22:18:08.760 回答
1

我认为您的第二个查询根本不会执行,因为该实体已经在一级缓存中。

由于您的事务尚未提交,因此您看不到底层数据库中的更改。

(这只是一个猜测)

于 2013-10-11T15:47:13.433 回答
0

这只是一个猜测,因为您没有提供很多细节,但我想您myObject.setMyDefaultProperty(1)在会话打开时执行您的操作。

在这种情况下,请注意您不需要实际执行 asession.update(myObject)来保存更改。当数据库更新由休眠透明地完成时,这是名义上的情况。

所以,事实上,我认为您的更改已保存...(但未提交,当然,因此在您签入数据库时​​看不到)

要验证这一点,您应该启用 hibernate.show_sql 选项。您将看到是否触发了 Update 语句(我建议始终在开发阶段启用此选项)

于 2013-10-11T22:02:51.043 回答