【问题标题】:Counter Using Spring's JPA Repositories使用 Spring 的 JPA 存储库进行计数器
【发布时间】:2017-01-17 17:30:42
【问题描述】:

我很确定这是一种常见情况 - 我有一个表,其中有一列用作计数器。我需要增加值并且需要知道增加的值。

我可以用 Spring 的 JPA 存储库做这样的事情:

@Transactional
public getNextValue(){
    DataPO po = repository.find("someId");
    po.setCounter(po.getCounter+1);
    repository.save(po);
}

它的缺点是它使用锁定,因此速度很慢。

我读到了一种使用 last_insert_id 来有效执行此操作的方法,但我发现的示例不使用存储库,它们直接使用 EntityManagersample

这是来自链接页面:

Query query = entityManager.createNativeQuery("UPDATE counter SET value = LAST_INSERT_ID(value + 1) WHERE name = :name");
query.setParameter("name", client.getName());
query.executeUpdate();

query = entityManager.createNativeQuery("SELECT LAST_INSERT_ID()");
long value = ((BigInteger) query.getSingleResult()).longValue();
value = value - 1;

有没有办法使用 Spring 的 JPA 存储库来做到这一点?我在文档中找不到任何内容:Spring's JPA Repositories

对于 JPA 存储库,我可以遵循任何其他有效的方法吗?

提前感谢您的帮助!

【问题讨论】:

  • 我在写关于锁定的文章时认为这很清楚。我应该更准确地说。它是多线程的,计数器没有 ID。我需要更新计数器并将其取回,这样可以有效地避免引入竞争条件。

标签: java mysql jpa spring-data spring-data-jpa


【解决方案1】:

您可以使用 Spring Data JPA 中的 Native Queries

在你的情况下:

public interface CounterRepository extends JpaRepository<Counter, Long>{

    @Modifying
    @Query(value = "UPDATE Counter SET value = LAST_INSERT_ID(value + 1) WHERE name = ?1", nativeQuery = true)
    int updateCounterByName(String name);

    @Query(value = "SELECT LAST_INSERT_ID()", nativeQuery = true)
    int getLastInsertId();

    Counter findOneByName(String name);

}

在我的 GitHub 存储库中查看 Complete Project

【讨论】:

    猜你喜欢
    • 2020-01-01
    • 2017-05-26
    • 2019-11-29
    • 1970-01-01
    • 2019-05-29
    • 2019-05-10
    • 2013-08-23
    • 1970-01-01
    • 2023-01-14
    相关资源
    最近更新 更多