Java 带和函数的弹簧规格说明
我正在尝试spring规范中的求和函数,如下所示:Java 带和函数的弹簧规格说明,java,spring,spring-mvc,jpa,specifications,Java,Spring,Spring Mvc,Jpa,Specifications,我正在尝试spring规范中的求和函数,如下所示: @Override public Predicate toPredicate(Root<Stock> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression = root.get("qty"); query.select(builder.sum(expression)); return null; } 但S
@Override
public Predicate toPredicate(Root<Stock> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Path expression = root.get("qty");
query.select(builder.sum(expression));
return null;
}
但Spring并没有创建求和函数,而是在执行:
SELECT o.qty FROM Stock o
我检查了这么多堆栈溢出问题,但没有以规范的方式给出答案,大多数人使用JPQL
作为@Query
注释。但我的进一步查询和设计非常复杂,所以我只能使用规范。因为我需要完全动态的查询
也有类似的,也有 我认为这是不可能的。 原因如下。 我指的是SpringJPA1.7.3(可以在这里找到源代码:) JPA规范通过JPA存储库使用,例如:
myRepo.findAll(mySpec);
此函数的源代码为:
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll(org.springframework.data.jpa.domain.Specification)
*/
public List<T> findAll(Specification<T> spec) {
return getQuery(spec, (Sort) null).getResultList();
}
正如您所看到的,这种类型的调用显式地选择root(在您的例子中是类型T或Stock
),并且由于它是在将规范应用于条件查询之后执行的,所以它会覆盖您在规范中所做的任何操作
不过,还有一个解决办法
您可以扩展现有的JPA存储库类:
public class MyRepositoryImpl<T>
extends SimpleJpaRepository<T, Integer> implements MyRepository<T>
{
其中,Stock\uu
是Stock
实体的元模型类
这是一个非常简单的示例,只有一个字段,无法选择聚合操作。它可以扩展以适应一个人的需要 我的IDE指向
Root=query.from(getDomainClass())无法将T解析为类型的代码>。你知道为什么吗?T是类的类型参数。你可能没有。在这种情况下,您可以尝试Root
。
/**
* Creates a {@link TypedQuery} for the given {@link Specification} and {@link Sort}.
*
* @param spec can be {@literal null}.
* @param sort can be {@literal null}.
* @return
*/
protected TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
Root<T> root = applySpecificationToCriteria(spec, query);
query.select(root);
if (sort != null) {
query.orderBy(toOrders(sort, root, builder));
}
return applyRepositoryMethodMetadata(em.createQuery(query));
}
public class MyRepositoryImpl<T>
extends SimpleJpaRepository<T, Integer> implements MyRepository<T>
{
public <P> P calcAggregate(EntitySpecification<T> spec, SingularAttribute<?,P> column)
{
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<P> query = criteriaBuilder.createQuery(column.getJavaType());
if (spec != null)
{
Root<T> root = query.from(getDomainClass());
query.where(spec.toPredicate(root, query, criteriaBuilder));
query.select(criteriaBuilder.sum(root.get(column.getName())));
}
TypedQuery<P> typedQuery = em.createQuery(query);
P result = typedQuery.getSingleResult();
return result;
}
myRepo.calcAggregate(mySpec, Stock_.qty);