gpt4 book ai didi

java - 具有 Sum 函数的 Spring 规范

转载 作者:行者123 更新时间:2023-11-29 08:42:36 25 4
gpt4 key购买 nike

我正在尝试如下所示的 spring 规范中的求和函数:

@Override
public Predicate toPredicate(Root<Stock> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Path expression = root.get("qty");
query.select(builder.sum(expression));
return null;
}

我要执行的查询是:

SELECT SUM(o.qty) FROM Stock o;

但是 Spring 并没有创建求和函数,而是执行了这个:

SELECT o.qty FROM Stock o

我检查了很多 Stack Overflow 问题,但在规范方式中没有答案,大多数人为此使用 JPQL 作为 @Query 注释。但是我进一步的查询和设计非常复杂,所以我只能使用规范。因为我需要完全动态的查询。

有类似的question还有,和this以及。

最佳答案

我认为开箱即用是不可能的。这是原因。我指的是 Spring JPA 1.7.3(源代码可以在这里找到:http://grepcode.com/snapshot/repo1.maven.org/maven2/org.springframework.data/spring-data-jpa/1.7.3.RELEASE/)

通过 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();
}

这里是第一个问题:返回类型和查询类型绑定(bind)到实体类型 T。在您的情况下,这意味着返回结果将是 Stock< 的列表 实体。

第二个问题是选择列表在 getQuery() 函数中的组成方式:

/**
* 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));
}

如您所见,这种类型的调用显式选择根(在您的情况下是 T 或 Stock 类型)并且由于它是在将规范应用于标准查询之后执行的,因此它会覆盖您在规范。

不过,有一个解决方法。

您可以扩展现有的 JPA 存储库类:

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);

其中 Stock_Stock 实体的元模型类。

这是一个非常简单的示例,只有一个字段并且无法选择聚合操作。它可以扩展以满足一个人的需要。

关于java - 具有 Sum 函数的 Spring 规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38934549/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com