java - 使用 JpaSpecificationExecutor 时使用 QueryHint

标签 java spring-data eclipselink specification-pattern

我使用 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 的查询提示的方式是上面的,
@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这还没有解决。

最佳答案

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

1) Is the query already provided by the existing interfaces of spring-data like CrudRepository, PagingAndSortingRepository, JpaRepository etc?
Examples: saveAndFlush or findAll methods, more in docs.


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

2) Can I create a method using keywords inside method names?
Examples: count, more in docs.


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

    Long countByTitle(String title);

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

3) Can I create a custom query method writing JPQL?
Examples: docs.
In this case spring data does not try to create the query using keywords inside method names, so the method names can be whatever you wish.


@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) Do I want variable column names or variable where conditions? Then the solution is the Specification.
Example: docs, so 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) Do I want more? The solution is to get the EntityManager and use it like I used it without the spring data library. (This is the answer to this so question)
Example: so answer, more in 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 {
}

关于java - 使用 JpaSpecificationExecutor 时使用 QueryHint,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48520827/

相关文章:

java.lang.OutOfMemory错误: GC overhead limit exceeded JAVA

java - 如何从垃圾邮件 System.out 中阻止 apache.commons.logging?

JavaCL - 管理非常大的图像处理

java - 对象枚举总是返回空值

java - SpringMongo - 发现文档结构

java - MOXy 不导入它生成的其他模式

java - Spring 数据 neo4j LIKE 查询不起作用

java - @Controller导致java.lang.NoClassDefFoundError : javax/servlet/http/HttpServletRequest

java - 配置 Spring Data Repository 类以针对读取/选择方法命中 read_replica_db 并针对写入/插入方法命中 main_db ?

java - javase项目中的Eclipselink问题