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

探讨了在Hibernate中使用实体删除方法可能导致的事务内SQL执行顺序问题,并提供了一种通过执行自定义SQL来确保正确执行顺序的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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的执行顺序。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值