【问题标题】:hibernate - while updating NonUniqueObjectException with pessimistic lock "upgrade"hibernate - 在使用悲观锁“升级”更新 NonUniqueObjectException 时
【发布时间】:2011-02-22 13:04:20
【问题描述】:

休眠 3.6.0 最终版

我用过悲观锁

LockOptions - 因为 LockMode 不起作用,即“select ... for update”“for update”没有在 sql 中生成,这就是原因。

session.saveOrUpdate 错误:

org.hibernate.NonUniqueObjectException: 不同的对象具有相同的 标识符值已经 与会话相关联: [com.hermes.data.RateCode#RateCodeId{roomId=6836date=2011-02-01}

RateCode.hbm.xml

<class catalog="hermes" name="com.hermes.data.RateCode" table="ratecodes">
    <composite-id class="com.hermes.data.RateCodeId" name="id">
      <key-property name="roomId" type="int">
        <column name="roomId"/>
      </key-property>
      <key-property name="date" type="date">
        <column length="10" name="date" />
      </key-property>
    </composite-id>

java代码

for (int i = 0; i < roomId.length; i++) {
                existingRateCodeList = getRateCodeRoom(session, Integer.parseInt(roomId[i]), newRateCodeRange.getStartDate(), newRateCodeRange.getEndDate(), true, LockOptions.UPGRADE);
                updateRecord = existingRateCodeList.size();
                remainingRecord = totleRecord - updateRecord;

                if (existingRateCodeList.size() > 0) {
                    //update
                    updateOccured = true;
                    it = existingRateCodeList.iterator();
                    while (it.hasNext()) {
                        existingRateCode = (RateCode) it.next();

                        updatedRecordList.add(existingRateCode.getId());
                        newRateCodeRange.setId(existingRateCode.getId());

                        session.saveOrUpdate(newRateCodeRange);
                        session.flush();
                        session.clear();
                    }
                    tx.commit();
                }

....... 获取相同会话和/或另一个会话的列表。

合并

错误: org.hibernate.StaleObjectStateException: 行已被其他人更新或删除 交易(或未保存的值映射 不正确): [com.hermes.data.RateCode#RateCodeId{roomId=6836date=2011-02-01}

public List<RateCode> getRateCodeRoom(Session session, int roomId, Date from, Date to, boolean refreshCache, LockOptions lockOptions) {

        Query q = session.createQuery(
                "from RateCode rr where rr.id.roomId=:roomId and rr.id.date>=:from and rr.id.date<=:to order by rr.id.date").setInteger("roomId", roomId).setParameter("from", from).setParameter("to", to).setCacheable(true).setCacheMode(refreshCache ? CacheMode.REFRESH : CacheMode.NORMAL);

        if (lockOptions != null) {
            q.setLockOptions(lockOptions);
        }
        return q.list();
    }

【问题讨论】:

    标签: hibernate hibernate-mapping


    【解决方案1】:

    saveOrUpdate 获取一个分离的实例 (newRateCodeRange) 并尝试将其附加到会话。它的文档说,如果具有相同 ID 的同一实体的另一个实例已经与会话相关联,则会引发异常(您遇到的那个),这里就是这种情况 (existingRateCode)。

    您可能应该使用merge 方法将分离实例的状态复制到附加实例。

    【讨论】:

    • 我也尝试过合并,但出现错误org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.hermes.data.RateCode#RateCodeId{roomId=6836date=2011-02-01}
    • 这个异常意味着你试图保存一个实体,它的版本字段与你数据库中存储的版本相比已经过时。您尝试保存的实体的版本(例如)等于 3,而数据库中的版本是 4 或 5,这意味着在您加载实体和你保存它的那一刻。这也可能意味着您尝试多次合并同一个分离实体,而不从数据库中刷新其版本字段。
    猜你喜欢
    • 2013-09-16
    • 2014-08-30
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多