Spring 引导 SUM(列)与规范
Spring boot SUM(column) with specification
我有一个实体,说:
class MyEntity {
Long id;
String attr1;
String attr2;
String attr3;
String attr4;
Double attr5;
}
我使用 Specification
来查询按属性筛选的结果,例如:
class MySpecification implements Specification<MyEntity> {
private String attr1;
private String attr2;
private String attr3;
private String attr4;
@Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> restriction = new ArrayList<>();
if (!StringUtils.isEmpty(attr1)) {
restriction.add(criteriaBuilder.equal(root.get("attr1"), attr1));
}
if (!StringUtils.isEmpty(attr2)) {
restriction.add(criteriaBuilder.equal(root.get("attr2"), attr2));
}
// And so on
Predicate predicate = criteriaBuilder.disjunction();
predicate.getExpressions().add(criteriaBuilder.and(restriction.toArray(new Predicate[restriction.size()])));
return predicate;
}
}
现在我想通过 Specification
得到 attr5
的总和,我该怎么做?
先谢谢你。
经过一番研究,这里是解决方案:
创建接口:
interface MyRepositoryCustom {
<S extends Number> S sum(Specification<MyEntity> spec, Class<S> resultType, String fieldName);
}
实施:
@Repository
class MyRepositoryCustomImpl implements MyRepositoryCustom {
@Autowired
private EntityManager entityManager;
@Override
public <S extends Number> S sum(Specification<MyEntity> spec, Class<S> resultType, String fieldName) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<S> query = builder.createQuery(resultType);
Root<MyEntity> root = applySpecificationToCriteria(spec, query);
query.select(builder.sum(root.get(fieldName).as(resultType)));
TypedQuery<S> typedQuery = entityManager.createQuery(query);
return typedQuery.getSingleResult();
}
protected <S> Root<MyEntity> applySpecificationToCriteria(Specification<MyEntity> spec, CriteriaQuery<S> query) {
Root<MyEntity> root = query.from(MyEntity.class);
if (spec == null) {
return root;
}
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
Predicate predicate = spec.toPredicate(root, query, builder);
if (predicate != null) {
query.where(predicate);
}
return root;
}
}
主存储库应同时扩展 JpaRepository
和 MyRepositoryCustom
:
@Repository
interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyRepositoryCustom {
}
我有一个实体,说:
class MyEntity {
Long id;
String attr1;
String attr2;
String attr3;
String attr4;
Double attr5;
}
我使用 Specification
来查询按属性筛选的结果,例如:
class MySpecification implements Specification<MyEntity> {
private String attr1;
private String attr2;
private String attr3;
private String attr4;
@Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
List<Predicate> restriction = new ArrayList<>();
if (!StringUtils.isEmpty(attr1)) {
restriction.add(criteriaBuilder.equal(root.get("attr1"), attr1));
}
if (!StringUtils.isEmpty(attr2)) {
restriction.add(criteriaBuilder.equal(root.get("attr2"), attr2));
}
// And so on
Predicate predicate = criteriaBuilder.disjunction();
predicate.getExpressions().add(criteriaBuilder.and(restriction.toArray(new Predicate[restriction.size()])));
return predicate;
}
}
现在我想通过 Specification
得到 attr5
的总和,我该怎么做?
先谢谢你。
经过一番研究,这里是解决方案:
创建接口:
interface MyRepositoryCustom {
<S extends Number> S sum(Specification<MyEntity> spec, Class<S> resultType, String fieldName);
}
实施:
@Repository
class MyRepositoryCustomImpl implements MyRepositoryCustom {
@Autowired
private EntityManager entityManager;
@Override
public <S extends Number> S sum(Specification<MyEntity> spec, Class<S> resultType, String fieldName) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<S> query = builder.createQuery(resultType);
Root<MyEntity> root = applySpecificationToCriteria(spec, query);
query.select(builder.sum(root.get(fieldName).as(resultType)));
TypedQuery<S> typedQuery = entityManager.createQuery(query);
return typedQuery.getSingleResult();
}
protected <S> Root<MyEntity> applySpecificationToCriteria(Specification<MyEntity> spec, CriteriaQuery<S> query) {
Root<MyEntity> root = query.from(MyEntity.class);
if (spec == null) {
return root;
}
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
Predicate predicate = spec.toPredicate(root, query, builder);
if (predicate != null) {
query.where(predicate);
}
return root;
}
}
主存储库应同时扩展 JpaRepository
和 MyRepositoryCustom
:
@Repository
interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyRepositoryCustom {
}