hibernate使用delete(Entity)方法的顺序

hibernate为我们提供了删除直接根据实体参数删除数据的方法:

HibernateTemplate().delete(entity);

 

public void delete(final Object entity, final LockMode lockMode) throws DataAccessException {
		executeWithNativeSession(new HibernateCallback<Object>() {
			public Object doInHibernate(Session session) throws HibernateException {
				checkWriteOperationAllowed(session);
				if (lockMode != null) {
					session.lock(entity, lockMode);
				}
				session.delete(entity);
				return null;
			}
		});
	}

这是实现的源码,此处只是把实体从session中删掉,等待事务提交时统一生成sql语句。

 


 

 

 

所以这种方式不能保证在同一个事务中的sql执行顺序,假设有这样的代码在程序中:

 

需要在事务中先执行删除,再执行插入。在提交事务时,就发生主键冲突的错误。

经查,hibernate在向db提交缓存的sql时,是按insert、update、delete的顺序提交。这就导致在提交insert语句时出错。 

 

rentDeliveryChargeDao.delete(rentDeliveryCharge);

rentDeliveryKeyDao.delete(rentDeliveryKey);

 

rentDeliveryChargeDao.save(deliveryCharge);

rentDeliveryKeyDao.save(rentDeliveryKey);

 

如果此时有数据库唯一性限制的话,程序可能会报错,主要是由于在同一个事务中不保证sql执行顺序。

 

遇到此类问题应改为以下:

 

rentDeliveryChargeDao.deleteByRentContractId(rentContractId);

rentDeliveryKeyDao.delDeliveryKeyByContractId(rentContractId);

后者是底层调用:

public int bulkUpdate(final String queryString, final Object... values) throws DataAccessException {
		return executeWithNativeSession(new HibernateCallback<Integer>() {
			public Integer doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(queryString);
				prepareQuery(queryObject);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return queryObject.executeUpdate();
			}
		});
	}

 

这样就能保证事务中sql的执行顺序。

 

猜你喜欢

转载自youyanweixiao.iteye.com/blog/2352521