【问题标题】:Find Last item with queryDSL and spring-data-jpa implementation with LockMode查找带有 queryDSL 的最后一项和带有 LockMode 的 spring-data-jpa 实现
【发布时间】:2017-03-08 16:54:11
【问题描述】:

我想使用 Spring-Data-JPA(Hibernate 实现)和 QueryDSL(类型安全)从表“product”中查找最后插入的项目以生成 SQL:SELECT * FROM product ORDER BY id DESC LIMIT 1

我使用 @Transactional 从 Service 调用 findLast() 并希望 setLockMode(LockModeType.PESSIMISTIC_WRITE) 并在此 SQL 查询中添加“SELECT .. FOR UPDATE”。

public class ProductRepositoryImpl extends QueryDslRepositorySupport implements ProductRepositoryCustom {

    public ProductRepositoryImpl() {
        super(Product.class);
    }

    //SELECT * FROM PRODUCTS ORDER BY ID DESC LIMIT 1
    @Override
    public Product findLast() {
        QProduct product = QProduct.product;
        return from(product).orderBy(product.id.desc()).limit(1L).fetchOne();
    }
}

这是生成的 SQL

Hibernate: select * from ( select product0_.id as id11, product0_.description as description21, product0_.price as price31, product0_.productStatus as productStatus41, product0_.quantity as quantity51 from PRODUCTS product0 order by product0.id desc ) where行数

问题:在扩展 org.springframework.data.jpa.repository.support.QueryDslRepositorySupport 的存储库中添加 setLockMode() 的最佳方法是什么?

我已经尝试过了,但它返回 Object 并且需要转换(产品):

getQuerydsl().createQuery(product)
.setLockMode(LockModeType.PESSIMISTIC_WRITE).orderBy(product.id.desc()).limit(1L).fetchOne();

【问题讨论】:

  • 从生成的 SQL 来看,似乎并没有忽略限制,只是它使用了数据库的内部 rownum 语义来返回 rownum <= 1 的所有行跨度>
  • 是的,但是在子查询中执行,这不能与使用“SELECT .. FOR UPDATE”锁定选定的行一起工作,我检查了如果我跳过 limit() 生成的 SQL 是相同的 rownum
  • 如果指定limit() 并告诉它调用fetch()fetchResults() 会怎样。生成的 SQL 是否按预期工作?
  • 我的错,它是 Oracle 数据库,并且限制按预期工作。

标签: hibernate spring-data-jpa querydsl


【解决方案1】:

尝试使用这部分代码,我认为它会像这样工作:

  QProduct product = QProduct.product;
 return (Product)getQuerydsl().createQuery(product)
.setLockMode(LockModeType.PESSIMISTIC_WRITE).orderBy(product.id.desc())
.limit(1L).fetchOne();

Hibernate 将生成以下查询: Hibernate: select * from ( select product0_.id as id1_1_, ...... from PRODUCTS product0_ order by product0_.id desc ) where rownum

休眠:选择 product0_.id 作为 id1_1_, .... from PRODUCTS product0_ where product0_.id=?更新

注意:有两个 SQL 查询,只能通过 ID 锁定行。 问题是结构性的,最好分开查询而不是让 Hibernate 这样做。

【讨论】:

  • 是的,你是对的。更好的解决方案是不要尝试使用一个自定义 SQL 查询进行锁定,而是首先选择最后一行而不进行锁定。这可以通过方法名称使用 spring-data CrudRepository 查询轻松完成,例如:findTop1ByOrderByIdDesc() 和旁边有 @Lock(LockModeType.PESSIMISTIC_WRITE) 产品 findById(Long id);
猜你喜欢
  • 2020-01-12
  • 2016-01-12
  • 2012-11-09
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 2020-06-16
  • 2016-08-04
相关资源
最近更新 更多