Hibernate 带Postgres的Spring数据悲观锁超时
我在获取Spring数据以发送postgres以更新NOWAIT时失败 我在存储库中尝试了以下方法:Hibernate 带Postgres的Spring数据悲观锁超时,hibernate,postgresql,jpa,spring-data,Hibernate,Postgresql,Jpa,Spring Data,我在获取Spring数据以发送postgres以更新NOWAIT时失败 我在存储库中尝试了以下方法: @Lock(value = LockModeType.PESSIMISTIC_WRITE) MyObject findByUuid(String uuid); 配置(代码段) 我甚至在我的服务中注入EntityManager,这将返回0: info(em.getProperties().get(“javax.persistence.lock.timeout”) 但是上面只给了我“更新”,NOW
@Lock(value = LockModeType.PESSIMISTIC_WRITE)
MyObject findByUuid(String uuid);
配置(代码段)
我甚至在我的服务中注入EntityManager,这将返回0:
info(em.getProperties().get(“javax.persistence.lock.timeout”)
但是上面只给了我“更新”,NOWAIT部分没有被设置。我是否设置了正确的东西(从另一篇文章来看,这应该是可行的)
这让我更接近,尽管我不喜欢使用原始sql
@Lock(value = LockModeType.PESSIMISTIC_WRITE)
@Query(value = "SELECT * FROM the_table WHERE uuid = :uuid FOR UPDATE NOWAIT", nativeQuery = true)
MyObject findByUuid(@Param("uuid") String uuid);
这确实给了我一个锁异常,但是Spring修饰的服务(代理)在返回时抛出一个事务/回滚异常,这意味着我不能在方法上给出我需要的返回值
问题:
1) 如何获取Spring数据以添加NOWAIT?
2) 是否有方法返回值?我怀疑我需要自己处理事务,或者更改逻辑流?不确定Spring是否处理NOWAIT,它是否会有不同的行为
我意识到也有类似的问题,但这略有不同。
我使用的是hibernate 4.2.15,spring数据jpa 1.7.1,postgres sql 9.3。使用悲观的强制增量javax.persistence.lock.timeout在如下提供的情况下对我也不起作用
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})
但后来我尝试了其他有效的方法。现在,我不再使用@Repository和crudepository,而是使用实体管理器配置我的hibernate。使用createQuery以及锁定和设置锁定超时。此配置正在按预期工作。我有两个并行运行的事务,试图在DB中锁定完全相同的行。第一个事务能够获取写锁,并在释放锁之前保持锁大约10秒。同时,第二个事务尝试获取同一行上的锁,但由于javax.persistence.lock.timeout设置为15秒,因此它等待释放锁,然后获取自己的锁。因此使流序列化
@Component
public class Repository {
@PersistenceContext
private EntityManager em;
public Optional<Cache> getById(int id){
List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
.setParameter(1, id)
.setHint("javax.persistence.lock.timeout", 15000)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.getResultList();
return Optional.ofNullable(list.get(0));
}
public void save(Cache cache) {
cache = em.find(Cache.class, cache.getId());
em.merge(cache);
}
}
@组件
公共类存储库{
@持久上下文
私人实体管理者;
公共可选getById(int-id){
List List=em.createQuery(“从缓存c中选择c,其中c.id=?1”)
.setParameter(1,id)
.setHint(“javax.persistence.lock.timeout”,15000)
.setLockMode(LockModeType.悲观写入)
.getResultList();
返回可选的.ofNullable(list.get(0));
}
公共无效保存(缓存){
cache=em.find(cache.class,cache.getId());
em.merge(缓存);
}
}
确保此锁机制位于事务内部,因为在提交或回滚事务时,锁将被释放 SpringDataJPA不会向Postgresql发送任何内容,您的JPA提供商会发送。Hibernate(您可能正在使用的)支持添加NOWAIT吗?好问题。看看我们使用的类(PostgressQL82方言),它有以下实现:getForUpdateNowaitString(…){返回这个。getForUpdateString(…)+“nowait”}基于HH-6452,应该这样做,这是唯一要检查的吗?然而,方言没有设置正确,所以它不工作,现在它是。这就解决了这个问题,谢谢@NeilStockton。虽然这个代码片段可以解决这个问题,但它确实有助于提高您文章的质量。请记住,您将在将来回答读者的问题,这些人可能不知道您的代码建议的原因。还请尽量不要用解释性注释挤满你的代码,这会降低代码和解释的可读性!不知为什么,这确实有帮助
@Component
public class Repository {
@PersistenceContext
private EntityManager em;
public Optional<Cache> getById(int id){
List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
.setParameter(1, id)
.setHint("javax.persistence.lock.timeout", 15000)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.getResultList();
return Optional.ofNullable(list.get(0));
}
public void save(Cache cache) {
cache = em.find(Cache.class, cache.getId());
em.merge(cache);
}
}