我认为这几乎不可能或非常棘手。我正在使用CriteriaBuilder,JPA 2.0,Hibernate和MariaDB,并希望使用CriteriaBuilder构建以下查询:
SELECT COUNT(*) FROM
(SELECT DISTINCT(SomeColumn) // I think this is not possible?
FROM MyTable
WHERE ... COMPLEX CLAUSE ...
GROUP BY SomeColumn) MyTable
我的问题:可能吗?如果,怎么样?
感谢您关注此事!
标记
答案 0 :(得分:2)
此示例假定您正在使用Metamodel生成。
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Subquery<SomeColumnType> subcq = cq.subquery(SomeColumnType.class);
Root<MyTable> from = subcq.from(MyTable.class);
subcq.select(from.get(MyTable_.someColumn));
subcq.where(** complex where statements **);
subcq.groupBy(from.get(MyTable_.someColumn));
cq.select(cb.count(subcq));
答案 1 :(得分:1)
我有一个类似的问题,按元素计算不同的组,并偶然发现了这个线程,基于我想出的现有答案
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
Root<Jpa1> countRoot = countQuery.from(Jpa1.class);
Subquery<Long> query = countQuery.subquery(Long.class);
Root<Jpa1> root = query.from(Jpa1.class);
applyFilter(query, root);
query.groupBy(root.get("groupBy_column1"), root.get("groupBy_column2"));
query.select(builder.min(root.get("id_column")));
countQuery.where(builder.in(countRoot.get("id_column")).value(query));
return countQuery.select(builder.count(countRoot.get("id_column")));
答案 2 :(得分:0)
如果您具有Spring Boot并且想要执行相同的操作,那么有一个更好的解决方法,该解决方法只能通过使用本机SQL_CALC_FOUND_ROWS
和FOUND_ROWS
来针对MySql 5 / Maria工作(它不会无法在MySQL 8上运行);
这种集成的主要思想是Spring-Data的灵活性以及如下重写默认JpaRepositoryFactoryBean
的功能
步骤1-创建自定义CustomJpaRepositoryFactoryBean
:
/**
*
* @author ehakawati
*
* @param <R>
* @param <T>
* @param <I>
*/
public class CustomJpaRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
public CustomJpaRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
super(repositoryInterface);
}
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
RepositoryFactorySupport repositoryFactorySupport = super.createRepositoryFactory(entityManager);
repositoryFactorySupport.setRepositoryBaseClass(CustomJpaRepository.class);
return repositoryFactorySupport;
}
}
步骤2-创建自定义CustomJpaRepository
/**
*
* @author ehakawati
*
* @param <T>
* @param <ID>
*/
public class CustomJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
implements Repository<T, ID> {
private final EntityManager em;
/**
*
* @param entityInformation
* @param entityManager
*/
public CustomJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
}
/**
*
* @param domainClass
* @param entityManager
*/
public CustomJpaRepository(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.em = entityManager;
}
/**
* Reads the given {@link TypedQuery} into a {@link Page} applying the given
* {@link Pageable} and {@link Specification}.
*
* @param query must not be {@literal null}.
* @param domainClass must not be {@literal null}.
* @param spec can be {@literal null}.
* @param pageable can be {@literal null}.
* @return
*/
protected <S extends T> Page<S> readPage(TypedQuery<S> query, final Class<S> domainClass, Pageable pageable,
@Nullable Specification<S> spec) {
if (pageable.isUnpaged()) {
return super.readPage(query, domainClass, pageable, spec);
}
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> getNativeCount());
}
/**
*
*/
protected long getNativeCount() {
final Query query = em.createNativeQuery("SELECT FOUND_ROWS() as `count`");
return ((BigInteger) query.getSingleResult()).longValue();
}
}
第3步-PageableQueriesInterceptor
:
/**
*
* @author ehakawati
*
* @param <T>
* @param <ID>
*/
public class PageableQueriesInterceptor extends EmptyInterceptor {
private static final Pattern PATTERN = Pattern.compile(".*?limit \\?(, \\?)?$");
private static final long serialVersionUID = 1L;
@Override
public String onPrepareStatement(String sql) {
if (PATTERN.matcher(sql).find()) {
sql = sql.replaceFirst("select", "select SQL_CALC_FOUND_ROWS ");
}
return sql;
}
}
第4步-启用PageableQueriesInterceptor
:
sprint.jpa.properties.hibernate.ejb.interceptor= com.****.****.******.betterpaging.PageableQueriesInterceptor
享受