【问题标题】:Use QueryHint when using JpaSpecificationExecutor使用 JpaSpecificationExecutor 时使用 QueryHint
【发布时间】:2018-07-09 07:17:06
【问题描述】:

我使用 spring 数据和 JpaSpecificationExecutor::findAll 方法来获取我的模型。调用此方法时如何使用查询提示?
上面的源代码工作正常,但我无法为我的 JPA 提供程序(在我的情况下为 EclipseLink)设置 QueryHint。

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product> {
}

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public List<Product> findByTitle(String locale, String titleToSearch) {
        return productRepository.findAll((Root<ProductCategory> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
            return builder.equal(builder.function("jsonb_extract_path_text", String.class, root.<String>get("title"), builder.literal(locale)), titleToSearch);
        });
    }
}

我使用spring-data使用Query Hints的方式如上,

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product> {

    @QueryHints(value = {
        @QueryHint(name = org.eclipse.persistence.config.QueryHints.BATCH_TYPE, value = "JOIN"),
        @QueryHint(name = org.eclipse.persistence.config.QueryHints.BATCH, value = "p.productCategory"),
        @QueryHint(name = org.eclipse.persistence.config.QueryHints.BATCH, value = "p.productFileList")
    }, forCounting = false)
    @Query("SELECT p FROM Product p")
    public List<Product> find();
}

我还发现了 this 尚未解决。

【问题讨论】:

  • 您是否尝试过覆盖ProductRepository界面中的findAll并添加查询提示?
  • ProductRepository 接口是在运行时由spring数据实现的(spring字节码检测)。 Spring 数据支持使用 spring 数据文档中描述的过程进行自定义实现。我会发布答案,因为这是我的解决方案。

标签: java spring-data eclipselink specification-pattern


【解决方案1】:

当我想使用 spring-data 创建查询时,我遵循上述算法。

1)spring-data的现有接口如CrudRepositoryPagingAndSortingRepositoryJpaRepository等是否已经提供了查询
示例:saveAndFlushfindAll 方法,更多在 docs

Product product = new Product();
// Setters..
productRepository.saveAndFlush();

2) 我可以在方法名称中使用关键字创建方法吗?
示例:count,更多内容请参见 docs

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {

    Long countByTitle(String title);

    List<Product> findByTitleLikeAndVisible(String title, boolean visible);
}

3) 我可以创建一个编写 JPQL 的自定义查询方法吗?
示例:docs.
在这种情况下,spring data 不会尝试使用方法名称中的关键字来创建查询,因此方法名称可以是任何你想要的。

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {

    @Query("SELECT COUNT(p) FROM Product p WHERE p.title=?1")
    Long countByTitle(String title);

    @Query("SELECT p FROM Product p WHERE p.title LIKE :title AND visible=true")
    List<Product> findByTitleLikeAndVisibleTrue(@Param("title") String title);
}

4) 我想要变量列名还是变量where 条件?那么解决方案就是规范。
示例:docsso answer

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product> {
}


@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public List<Product> findByColumn(String columnName, Object value) {
        return productRepository.find((Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
            return builder.and(builder.equal(root.<String>get(columnName), value));
        });
    }
}

5) 我想要更多吗? 解决方案是获取 EntityManager 并像我在没有 spring 数据库的情况下使用它一样使用它。 (这是这个问题的答案)
示例:so answer,更多在docs

// Create an interface and add the methods you wish to use with EntityManger.
public interface ProductRepositoryExt {
    public List<Product> findByTitle(String title);
}

// Implement the interface you created. Be careful the class name must be identical to the spring-data @Repository interface with the "Impl" appended.
public class ProductRepositoryImpl implements ProductRepositoryExt {

    @PersistenceContext
    private EntityManager em;

    @Override
    public List<Product> findByTitle(String title) {
//        em.getTransaction().begin();
        String sql = "SELECT p FROM Product p WHERE p.title=:title')";
        TypedQuery<ProductCategory> query = em.createQuery(sql, Product.class);
        query.setParameter("title", title);
        //  Add the query hints you wish..
        query.setHint(org.eclipse.persistence.config.QueryHints.BATCH_TYPE, "JOIN");
        query.setHint(org.eclipse.persistence.config.QueryHints.BATCH, "p.productCategory");

        return query.getResultList();
//        em.getTransaction().commit();
    }
}

// Extend this interface from your spring-data @Repository interface.
@Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, ProductCategoryRepositoryExt {
}

【讨论】:

  • 只是当前 Spring Data 2.2 中关于 解决方案 4) 的提示:方法 find 现在是 findAll.
猜你喜欢
  • 1970-01-01
  • 2014-10-25
  • 2022-06-15
  • 2014-01-10
  • 2016-05-14
  • 2019-11-29
  • 2014-12-05
  • 1970-01-01
  • 2019-08-19
相关资源
最近更新 更多