Postgres

时间:2015-07-10 22:48:55

标签: hibernate postgresql jpa spring-data

我没有成功让Spring Data向NOWAIT发送一个FOR更新的帖子。

我在存储库中试过这个:

@Lock(value = LockModeType.PESSIMISTIC_WRITE)
MyObject findByUuid(String uuid);

配置(摘录)

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "docsEntityManagerFactory",
    transactionManagerRef = "docsTransactionManager",

@Bean(name = "docsEntityManagerFactory")
public EntityManagerFactory docsEntityManagerFactory(DataSource docsDataSource) {
props.setProperty("javax.persistence.lock.timeout", "0");
...

我甚至在我的服务中注入了EntityManager,这返回0:

  

logger.info(em.getProperties()得到(" javax.persistence.lock.timeout&#34));

但是上面的内容只能让我获得" FOR UPDATE",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);

这确实给了我一个Lock异常,但是Spring装饰服务(代理)会在返回时抛出一个Transaction / Rollback异常,这意味着我不能给出我需要的方法的返回值。

问题: 1)如何让Spring Data添加NOWAIT? 2)有没有办法返回价值?我怀疑我需要自己处理事务,还是改变逻辑流程?如果Spring表现不同,不确定Spring是否处理NOWAIT。

我意识到有类似的问题,但这有点不同。 我正在使用hibernate 4.2.15,spring-data-jpa 1.7.1,postgres sql 9.3。

2 个答案:

答案 0 :(得分:0)

当像下面这样提供时,

javax.persistence.lock.timeout也不对我有用

@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})

但是后来我尝试了其他可行的方法。现在,我使用实体管理器配置休眠,而不是使用@Repository和CrudRepository。与锁定和设置锁定超时一起使用了createQuery。并且此配置按预期工作。我有两个并行运行的事务,并试图锁定数据库中完全相同的行。第一个事务能够获取WRITE锁定,并在释放锁定之前将其保持约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);
    }
}

确保此锁定机制在事务内部,因为在提交或回滚事务时将释放锁定。

答案 1 :(得分:-1)

使用PESSIMISTIC_FORCE_INCREMENT