spring数据不更新最新数据

wrrgggsh  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(307)

我的sql表中有一个字段,需要更新一个字段并返回一个唯一的id。但是看起来它没有在最新的数据上更新,特别是当我发出很多请求时。

@Transactional
public interface CompanyRepository extends CrudRepository<Company, Integer> {    
    @Modifying(clearAutomatically = true, flushAutomatically = true)
    @Query(value = "update Company c set c.accessId = :accessId WHERE c.id = :companyId AND c.accessId = :oldAccessId", nativeQuery = true)
    int updateAccessId(@Param("companyId") Integer companyId, @Param("accessId") Integer accessId, @Param("oldAccessId") Integer oldAccessId);
}

即使clearautomatically和flushautomatically都设置为true,它也不能处理最新的数据。
我可以看到两个更新查询都是成功的,oldaccessid都是相同的。
table的设计应该改变吗?
ps:我也尝试过没有nativequery=true。

b1zrtrql

b1zrtrql1#

这里有一个经典的竞赛条件。
两个线程读取相同的实体,具有相同的 accessId ,将其增量为1,然后使用问题中显示的方法编写结果。结果实际上只有一个更新。
有多种方法可以解决这个问题。
使用jpa和乐观锁。
假设你有一个属性 @Version 注解:您可以在单个事务方法中执行以下操作:
加载实体。
增加 accessId .
持久化实体。
如果另一个事务试图对同一个实体执行相同的操作,那么这两个事务中的一个将得到异常。在这种情况下,请重试,直到更新完成。
使用数据库。
使数据库中的读取和更新成为原子的。不要将新值作为参数传递,而是使用如下查询:

update Company c 
set c.accessId = c.accessId + 1 
WHERE c.id = :companyId

使其成为版本属性。
如上所述,jpa已经 @Version 每次更改都会更新的属性。取决于您可能提出的确切要求 accessId 只需输入该属性并自动更新即可。
检查是否更新了任何行。
根据您的评论,您的意图是基本上重新实现jpa对版本属性的处理。如果您这样做,您将缺少一个关键部分:通过比较返回值和1,检查更新是否实际更新了任何内容。

相关问题