hibernate - 用悲观锁“升级”更新NonUniqueObjectException

时间:2011-02-22 13:04:21

标签: hibernate hibernate-mapping

hibernate 3.6.0 final

我使用过悲观锁

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

session.saveOrUpdate 错误:

  

org.hibernate.NonUniqueObjectException:   具有相同的不同对象   标识符值已经存在   与会话相关联:   [com.hermes.data.RateCode#Rate​​CodeId {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#Rate​​CodeId {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();
    }

1 个答案:

答案 0 :(得分:3)

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

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