Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在使用Spring数据JPA查找实体时,如何启用LockModeType.悲观_写入?_Java_Spring_Jpa_Spring Data_Spring Data Jpa - Fatal编程技术网

Java 在使用Spring数据JPA查找实体时,如何启用LockModeType.悲观_写入?

Java 在使用Spring数据JPA查找实体时,如何启用LockModeType.悲观_写入?,java,spring,jpa,spring-data,spring-data-jpa,Java,Spring,Jpa,Spring Data,Spring Data Jpa,如何实现此代码的等效性: tx.begin(); Widget w = em.find(Widget.class, 1L, LockModeType.PESSIMISTIC_WRITE); w.decrementBy(4); em.flush(); tx.commit(); 。。。但是使用Spring和Spring数据JPA注释 我现有代码的基础是: @Service @Transactional(readOnly = true) public class WidgetServiceImpl

如何实现此代码的等效性:

tx.begin();
Widget w = em.find(Widget.class, 1L, LockModeType.PESSIMISTIC_WRITE);
w.decrementBy(4);
em.flush();
tx.commit();
。。。但是使用Spring和Spring数据JPA注释

我现有代码的基础是:

@Service
@Transactional(readOnly = true)
public class WidgetServiceImpl implements WidgetService
{
  /** The spring-data widget repository which extends CrudRepository<Widget, Long>. */
  @Autowired
  private WidgetRepository repo;

  @Transactional(readOnly = false)
  public void updateWidgetStock(Long id, int count)
  {
    Widget w = this.repo.findOne(id);
    w.decrementBy(4);
    this.repo.save(w);
  }
}
@服务
@事务(只读=真)
公共类WidgetServiceImpl实现WidgetService
{
/**扩展Crudepository的spring数据小部件存储库*/
@自动连线
私人回购;
@事务(只读=假)
public void updateWidgetStock(长id,整数计数)
{
Widget w=this.repo.findOne(id);
w、 递减(4);
本次回购保存(w);
}
}
但是我不知道如何指定
updateWidgetStock
方法中的所有内容都应该使用悲观锁集来完成

有一个Spring数据JPA注释
org.springframework.Data.JPA.repository.Lock
,它允许您设置
LockModeType
,但我不知道将它放在
updateWidgetStock
方法上是否有效。它听起来更像是WidgetRepository上的注释,因为Javadoc说:

org.springframework.data.jpa.repository
@目标(值=方法)
@保留期(值=运行时)
@记录的
公共@接口锁
注释,用于指定执行查询时要使用的LockModeType。在对查询方法使用查询时,或者从方法名称派生查询时,将对其进行计算

。。。所以这似乎没有什么帮助


如何使我的
updateWidgetStock()
方法使用
LockModeType.悲观写入
set执行?

如果您能够使用Spring数据1.6或更高版本,请忽略此答案并参考Oliver的答案。

Spring数据悲观
@Lock
注释仅适用于查询(如您所指出的)。据我所知,没有任何注释会影响整个事务。您可以创建一个
findByOnePessimistic
方法,该方法使用悲观锁调用
findByOne
,也可以更改
findByOne
以始终获得悲观锁

如果您想实现自己的解决方案,您可能可以。在发动机罩下,
@Lock
注释由
lockmodepopulatingmethodinterceptor
处理,它执行以下操作:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
interface WidgetRepository extends Repository<Widget, Long> {

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);
}

您可以创建一些静态锁管理器,它有一个
ThreadLocal
成员变量,然后在调用
bindResource
的每个存储库中的每个方法周围包装一个方面,并在
ThreadLocal
中设置锁模式。这将允许您在每个线程的基础上设置锁定模式。然后,您可以创建自己的
@MethodLockMode
注释,该注释将在一个方面中包装该方法,该方面在运行该方法之前设置线程特定的锁定模式,并在运行该方法之后将其清除。

@lock
从Spring Data JPA的1.6版开始,CRUD方法就支持它(事实上,已经有可用的). 有关更多详细信息,请参见此

对于该版本,您只需声明以下内容:

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
interface WidgetRepository extends Repository<Widget, Long> {

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);
}
接口WidgetRepository扩展存储库{
@锁(锁模式类型。悲观写入)
小部件findOne(长id);
}

这将导致备份存储库代理的CRUD实现部分将配置的
LockModeType
应用于
EntityManager

上的
find(…)
调用。如果您不想覆盖标准的
findOne()
方法,您可以通过使用
select。。。对于更新
查询,如下所示:

/**
 * Repository for Wallet.
 */
public interface WalletRepository extends CrudRepository<Wallet, Long>, JpaSpecificationExecutor<Wallet> {

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select w from Wallet w where w.id = :id")
    Wallet findOneForUpdate(@Param("id") Long id);
}

}

这两个问题的答案可能都很有帮助:如果查询在事务结束前都没有保留(因此包含以下任何更新),那么在查询上设置悲观锁有什么意义?在查询中获得的悲观锁应该保留到事务结束。后两段描述了如何创建一个事务,其中所有查询都获得了悲观锁。如果我当时理解正确,我只需使
findOne
使用悲观锁即可实现我想要的效果-该锁应保持到事务结束(将在my
updateWidgetStock()的末尾结束)
方法。对吗?请注意,从即将发布的Spring Data JPA的1.6版本开始,CRUD方法将支持使用
@Lock
。有关详细信息,请参阅此。在我的测试中,此@Lock已经可以与Spring Data JPA 1.4.1一起使用……但无论如何,问题是,我如何传递锁类型?我不想总是使用悲观锁,很多都是f senarios大部分是读的。但是当我知道我在写,并且会有争用时,我想使用一个悲观锁。我可以创建findOneLock(String,LockModeType)吗?啊,好的,请参见1.4.1。当我将其添加到重写的findOne时,它会工作,但当我将其添加到我自己的findByXxx时,它不会工作。主要问题仍然是,我如何在某些时间使用锁,但不是在所有时间都使用锁。与此相关的小问题。如果我注释方法“findOnePessimstic(…”,会考虑注释吗对于调用findOne(…)的默认实现,这将允许保持findOne的乐观锁定行为,并提供悲观锁定,而不需要@Query。您应该知道,在尝试使用spring data rest的情况下,您会遇到麻烦,因为spring data rest在执行以下操作时会执行只读事务:“select for update”是非法的-并且这些调用完全是findOne…如果@Lock放在方法名派生或查询(非本机)上,那么此时会考虑@Lock。如果根据业务逻辑,我需要相同名称的派生方法同时为悲观/无锁,该怎么办?如何克服它?不幸的是,这不会刷新
entityManager
缓存。您必须手动执行
entityManager.refresh(wallet)