The Hibernate version used in this article is 5.2.12.Final
JpaSpecificationExecutor interface functions that need to be implemented (except findOne)
package org.springframework.data.jpa.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
/**
* Interface to allow execution of {@link Specification}s based on the JPA criteria API.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
public interface JpaSpecificationExecutor<T> {
/**
* Returns all entities matching the given {@link Specification}.
*
* @param spec can be {@literal null}.
* @return never {@literal null}.
*/
List<T> findAll(@Nullable Specification<T> spec);
/**
* Returns a {@link Page} of entities matching the given {@link Specification}.
*
* @param spec can be {@literal null}.
* @param pageable must not be {@literal null}.
* @return never {@literal null}.
*/
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
/**
* Returns all entities matching the given {@link Specification} and {@link Sort}.
*
* @param spec can be {@literal null}.
* @param sort must not be {@literal null}.
* @return never {@literal null}.
*/
List<T> findAll(@Nullable Specification<T> spec, Sort sort);
/**
* Returns the number of instances that the given {@link Specification} will return.
*
* @param spec the {@link Specification} to count instances for. Can be {@literal null}.
* @return the number of instances.
*/
long count(@Nullable Specification<T> spec);
}
Needed dependency
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
</dependencies>
Configuration file hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.cj.jdbc.Driver
</property>
<!-- Assume test is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/jego?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&maxReconnects=20&serverTimezone=UTC
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping class="com.wl.hibernate.model.ContentInfo"/>
<mapping class="com.wl.hibernate.model.UsrUserArticle"/>
</session-factory>
</hibernate-configuration>
sessionUtil
package com.wl.hibernate.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Created by wl on 2018/5/13.
*/
public class SessionUtil {
private static final String HIBERNATE_CONFIG_LOCATION = "hibernate.cfg.xml";
private static SessionFactory sessionFactory;
static {
//默认加载classpath下hibernate.properties
sessionFactory = new Configuration().configure(HIBERNATE_CONFIG_LOCATION).buildSessionFactory();
}
public static Session getSession(){
return sessionFactory.openSession();
}
public static Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
public static void closeSession(Session session){
session.close();
}
}
Two entity classes
package com.wl.hibernate.model;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name = "content_info")
public class ContentInfo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "title")
private String title;
@Column(name = "content")
private String content;
@Column(name = "introduces")
private String introduces;
@Column(name = "recommend_value")
private Integer recommendValue;
@Column(name = "author", updatable = false)
private String author;
@Column(name = "create_time", insertable = false, updatable = false)
private Date createTime;
@Column(name = "modify_time", insertable = false, updatable = false)
private Date modifyTime;
public ContentInfo(){
}
public ContentInfo(Long id){
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getIntroduces() {
return introduces;
}
public void setIntroduces(String introduces) {
this.introduces = introduces;
}
public Integer getRecommendValue() {
return recommendValue;
}
public void setRecommendValue(Integer recommendValue) {
this.recommendValue = recommendValue;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getModifyTime() {
return modifyTime;
}
public void setModifyTime(Date modifyTime) {
this.modifyTime = modifyTime;
}
}
package com.wl.hibernate.model;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* Created by wl on 2018/1/18.
*/
@Entity
@Table(name = "usr_user_article")
public class UsrUserArticle implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "article_id", updatable = false, nullable = false)
@NotFound(action = NotFoundAction.IGNORE)
private ContentInfo contentInfo;
@Column(name = "create_time", insertable = false, updatable = false)
private Date createTime; //创建时间
@Column(name = "modify_time")
private Date modifyTime; //更新时间
public UsrUserArticle() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ContentInfo getContentInfo() {
return contentInfo;
}
public void setContentInfo(ContentInfo contentInfo) {
this.contentInfo = contentInfo;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getModifyTime() {
return modifyTime;
}
public void setModifyTime(Date modifyTime) {
this.modifyTime = modifyTime;
}
}
The following are the Sort and PageRequest needed to implement findAll
package com.wl.hibernate.sort;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wl on 2018/5/13.
*/
public class Sort{
public final List<Order> ORDERS = new ArrayList<>();
public Sort(Direction direction,String sortColumn){
Order order = new Order();
order.setDirection(direction);
order.setSortColumn(sortColumn);
ORDERS.add(order);
}
public Sort(Direction direction,String... sortColumns){
Order order = new Order();
order.setDirection(direction);
order.setSortColumn(sortColumns);
ORDERS.add(order);
}
public Sort add(Sort sort){
this.ORDERS.addAll(sort.ORDERS);
return this;
}
@SuppressWarnings("unchecked")
public static List<javax.persistence.criteria.Order> toJpaOrder(Sort sort, Root root, CriteriaBuilder cb) {
List<javax.persistence.criteria.Order> orderList = new ArrayList<>();
for(Order order : sort.ORDERS){
for(String property:order.getSortColumn()){
orderList.add(order.isAsc() ? cb.asc(get(property,root)) : cb.desc(get(property,root)));
}
}
return orderList;
}
private static Path get(String attributeName,Root root){
Path path = null;
String[] properties = attributeName.split("\\.");
for(String property : properties){
if(path == null) {
path = root.get(property);
}else{
path = path.get(property);
}
}
return path;
// return root.get(strs[0]).get(strs[1]);
}
private class Order{
private String[] sortColumn;
private Direction direction;
private Order(){
}
private String[] getSortColumn() {
return sortColumn;
}
private void setSortColumn(String... sortColumn) {
this.sortColumn = sortColumn;
}
public Direction getDirection() {
return direction;
}
private void setDirection(Direction direction) {
this.direction = direction;
}
private boolean isAsc() {
return Sort.Direction.isAsc(this.direction);
}
}
public enum Direction implements Serializable{
ASC,
DESC;
public final Integer VALUE;
Direction(){
this.VALUE = this.ordinal();
}
public static Direction fromString(String direction){
return isAsc(direction) ? ASC : DESC;
}
public static boolean isAsc(String direction){
return Direction.ASC.toString().equals(String.valueOf(direction).toUpperCase());
}
public static boolean isAsc(Direction direction){
return ASC == direction;
}
}
}
package com.wl.hibernate.page;
import com.wl.hibernate.sort.Sort;
/**
* Created by wl on 2018/5/13.
*/
public class PageRequest {
private int pageNum; //base 0
private int pageSize;
private Sort sort;
public PageRequest(){
}
public PageRequest(int pageNum,int pageSize){
this.pageNum = pageNum;
this.pageSize = pageSize;
}
public PageRequest(int pageNum,int pageSize,Sort sort){
this.pageNum = pageNum;
this.pageSize = pageSize;
this.sort = sort;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public Sort getSort() {
return sort;
}
public void setSort(Sort sort) {
this.sort = sort;
}
public int getOffSet() {
// if(pageNum == null || pageSize == null){
// throw new NullPointerException("pageSize or pageNum must not be null");
// }
if(pageNum < 0 || pageSize < 0){
throw new PageException("pageSize or pageNum must > 0");
}
return pageNum * pageSize;
}
private static class PageException extends RuntimeException{
private PageException(String msg){
super(msg);
}
}
}
package com.wl.hibernate.page;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wl on 2018/5/13.
*/
public class Page<T> {
private long totalCount;
private int pageNum;
private int pageSize;
private final List<T> elements = new ArrayList<>();
public Page(long totalCount,int pageSize,int pageNum,List<T> content){
this.totalCount = totalCount;
this.pageSize = pageSize;
this.pageNum = pageNum;
if(content != null && !content.isEmpty()){
this.elements.addAll(content);
}
}
public Page(){
// this.totalCount = 0L;
// this.pageSize = 0;
// this.pageNum = 0;
}
public long getTotalCount() {
return totalCount;
}
public void setTotalCount(long totalCount) {
this.totalCount = totalCount;
}
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List<T> getElements() {
return elements;
}
}
BaseDao
package com.wl.hibernate.dao;
import com.wl.hibernate.page.Page;
import com.wl.hibernate.page.PageRequest;
import com.wl.hibernate.sort.Sort;
import com.wl.hibernate.util.SessionUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
/**
* Created by wl on 2018/5/13.
*/
public abstract class BaseDao<T> {
private Class<T> tClass;
protected BaseDao(Class<T> t) {
this.tClass = t;
// try {
// this.tClass = (Class<T>) Class.forName(((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0].getTypeName());
// } catch (ClassNotFoundException e) {
// e.printStackTrace();
// }
}
protected Session getSession(){
return SessionUtil.getSession();
}
public void saveOrUpdate(T t){
Session session = getSession();
Transaction transaction = session.beginTransaction();
session.save(t);
session.flush();
transaction.commit();
SessionUtil.closeSession(session);
}
public List<T> findAll(Specification<T> specification){
Session session = getSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<T> query = getQuery(specification,cb,null);
List<T> contentInfoList = session.createQuery(query).list();
SessionUtil.closeSession(session);
return contentInfoList;
}
public List<T> findAll(Specification<T> specification, Sort sort){
Session session = getSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<T> query = getQuery(specification,cb,sort);
List<T> list = session.createQuery(query).list();
SessionUtil.closeSession(session);
return list;
}
public Page<T> findAll(Specification<T> specification, PageRequest pageRequest){
if(pageRequest == null){
List<T> content = this.findAll(specification);
if(content != null){
return new Page<>((long)content.size(),0,content.size(),content);
}
return new Page<>();
}
Session session = getSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
//先查询数量
CriteriaQuery<Long> countQuery = getCountQuery(cb,specification);
Long totalElements = totalCount(session,countQuery);
if(totalElements <= 0){
return new Page<>(0L,pageRequest.getPageSize(),pageRequest.getPageNum(),null);
}
CriteriaQuery<T> query = getQuery(specification,cb,pageRequest.getSort());
List<T> contentInfoList = session.createQuery(query).
setFirstResult(pageRequest.getOffSet()).setMaxResults(pageRequest.getPageSize()).getResultList();
SessionUtil.closeSession(session);
return new Page<>(totalElements,pageRequest.getPageSize(),pageRequest.getPageNum(),contentInfoList);
}
public long count(Specification<T> specification){
Session session = getSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Long> countQuery = getCountQuery(cb,specification);
return totalCount(session,countQuery);
}
private CriteriaQuery<T> getQuery(Specification<T> specification, CriteriaBuilder cb, Sort sort){
CriteriaQuery<T> query = cb.createQuery(tClass);
Root<T> root = query.from(tClass);
Predicate predicate = specification.toPredicate(root,query,cb); //必须
if(predicate != null){
query.where(predicate);
}
if(sort != null && sort.ORDERS.size() > 0){
query.orderBy(Sort.toJpaOrder(sort,root,cb));
}
return query;
}
private CriteriaQuery<Long> getCountQuery(CriteriaBuilder cb, Specification<T> specification){
CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
Root<T> root = countQuery.from(tClass);
if(specification != null) {
Predicate predicate = specification.toPredicate(root, countQuery, cb); //必须
if (predicate != null) {
countQuery.where(predicate);
}
}
if(countQuery.isDistinct()){
countQuery.select(cb.countDistinct(root));
}else{
countQuery.select(cb.count(root));
}
return countQuery;
}
private Long totalCount(Session session, CriteriaQuery<Long> countQuery){
List<Long> longList = session.createQuery(countQuery).getResultList();
Long total = 0L;
for(Long l : longList){
total += l;
}
return total;
}
public interface Specification<T>{
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
}
dao
package com.wl.hibernate.dao;
import com.wl.hibernate.model.UsrUserArticle;
/**
* Created by wl on 2018/5/28.
*/
public class UserArticleDao extends BaseDao<UsrUserArticle>{
public UserArticleDao() {
super(UsrUserArticle.class);
}
}
test
1.findAll
@Test
public void testFindAllArticle(){
List<UsrUserArticle> usrUserArticles = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(cb.equal(root.get("articleType"),1));
predicateList.add(cb.like(root.get("articleDescribes"),"%hhh%"));
predicateList.add(cb.greaterThan(root.get("createTime"),cb.literal(new Date())));
query.where(predicateList.toArray(new Predicate[predicateList.size()]));
query.groupBy(root.get("id"));
query.distinct(true);
return null;
}
});
System.out.println(usrUserArticles);
}
The generated sql is as follows
Hibernate:
select
distinct usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_
where
usruserart0_.article_type=1
and (
usruserart0_.article_describes like ?
)
and usruserart0_.create_time>?
and ?=1
group by
usruserart0_.id
If entity A is associated with entity B many-to-one or one-to-one, query entity A if you need to use a column in entity B as a condition, you can directly root.get("a").get("column"). For example, in this article, UsrUserArticle is associated with ContentInfo one-to-one. If you want to use authour in ContentInfo as a conditional query, you can use the following code
public void testFindAllArticle(){
List<UsrUserArticle> usrUserArticles = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(cb.equal(root.get("articleType"),1));
predicateList.add(cb.like(root.get("articleDescribes"),"%hhh%"));
predicateList.add(cb.greaterThan(root.get("createTime"),cb.literal(new Date())));
predicateList.add(cb.equal(root.get("contentInfo").get("author"),"wl")); //contentInfo 是UsrUserArticle对应ContentInfo的属性名称
query.where(predicateList.toArray(new Predicate[predicateList.size()]));
query.groupBy(root.get("id"));
query.distinct(true);
return null;
}
});
System.out.println(usrUserArticles);
}
sql is as follows
Hibernate:
select
distinct usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_ cross
join
content_info contentinf1_
where
usruserart0_.article_id=contentinf1_.id
and usruserart0_.article_type=1
and (
usruserart0_.article_describes like ?
)
and usruserart0_.create_time>?
and contentinf1_.author=?
group by
usruserart0_.id
If entity A and entity B have a many-to-many or one-to-many relationship and you need to use a certain column of the many party for conditional query, you can only use jpa join query (one-to-one, many-to-one can also use join query) here Use one-to-one join query as an example, basically the same as many-to-many one-to-many
code show as below
@Test
public void testFindAllArticle(){
List<UsrUserArticle> usrUserArticles = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicateList = new ArrayList<>();
predicateList.add(cb.equal(root.get("articleType"),1));
predicateList.add(cb.like(root.get("articleDescribes"),"%hhh%"));
predicateList.add(cb.greaterThan(root.get("createTime"),cb.literal(new Date())));
// predicateList.add(cb.equal(root.get("contentInfo").get("author"),"wl")); //contentInfo 是UsrUserArticle对应ContentInfo的属性名称
Join<UsrUserArticle,ContentInfo> join = root.join("contentInfo",JoinType.LEFT);
predicateList.add(cb.equal(join.get("author"),"wl"));
query.where(predicateList.toArray(new Predicate[predicateList.size()]));
query.groupBy(root.get("id"));
query.distinct(true);
return null;
}
});
System.out.println(usrUserArticles);
}
sql is as follows
Hibernate:
select
distinct usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_
left outer join
content_info contentinf1_
on usruserart0_.article_id=contentinf1_.id
where
usruserart0_.article_type=1
and (
usruserart0_.article_describes like ?
)
and usruserart0_.create_time>?
and contentinf1_.author=?
group by
usruserart0_.id
2.findAllWithSort
@Test
public void testFindAllArticleWithSort(){
List<UsrUserArticle> usrUserArticles = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return null;
}
},new Sort(Sort.Direction.DESC,"createTime"));
System.out.println(usrUserArticles);
}
sql
Hibernate:
select
usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_
order by
usruserart0_.create_time desc
If you want to sort by the associated contentInfo field
@Test
public void testFindAllArticleWithSort(){
List<UsrUserArticle> usrUserArticles = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return null;
}
},new Sort(Sort.Direction.DESC,"contentInfo.recommendValue"));
System.out.println(usrUserArticles);
}
sql
Hibernate:
select
usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_ cross
join
content_info contentinf1_
where
usruserart0_.article_id=contentinf1_.id
order by
contentinf1_.recommend_value desc
3.findWithPage
Code note pageNum base 1
@Test
public void testFindAllArticleWithPage(){
Page<UsrUserArticle> page = new UserArticleDao().findAll(new BaseDao.Specification<UsrUserArticle>() {
@Override
public Predicate toPredicate(Root<UsrUserArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return null;
}
},new PageRequest(1,10,new Sort(Sort.Direction.DESC,"createTime")));
System.out.println(page);
}
sql
Hibernate:
select
count(usruserart0_.id) as col_0_0_
from
usr_user_article usruserart0_
Hibernate:
select
usruserart0_.id as id1_1_,
usruserart0_.article_describes as article_2_1_,
usruserart0_.article_title as article_3_1_,
usruserart0_.article_type as article_4_1_,
usruserart0_.article_id as article_8_1_,
usruserart0_.create_time as create_t5_1_,
usruserart0_.itinerary_id as itinerar6_1_,
usruserart0_.modify_time as modify_t7_1_
from
usr_user_article usruserart0_
order by
usruserart0_.create_time desc limit ?,
?
ps: Before hibernate5.2, the Criteria interface in the org.hibernate package in hibernate-core may be used more. Its javadoc can clearly see its use.
/**
* <tt>Criteria</tt> is a simplified API for retrieving entities
* by composing <tt>Criterion</tt> objects. This is a very
* convenient approach for functionality like "search" screens
* where there is a variable number of conditions to be placed
* upon the result set.<br>
* <br>
* The <tt>Session</tt> is a factory for <tt>Criteria</tt>.
* <tt>Criterion</tt> instances are usually obtained via
* the factory methods on <tt>Restrictions</tt>. eg.
* <pre>
* List cats = session.createCriteria(Cat.class)
* .add( Restrictions.like("name", "Iz%") )
* .add( Restrictions.gt( "weight", new Float(minWeight) ) )
* .addOrder( Order.asc("age") )
* .list();
* </pre>
* You may navigate associations using <tt>createAlias()</tt> or
* <tt>createCriteria()</tt>.
* <pre>
* List cats = session.createCriteria(Cat.class)
* .createCriteria("kittens")
* .add( Restrictions.like("name", "Iz%") )
* .list();
* </pre>
* <pre>
* List cats = session.createCriteria(Cat.class)
* .createAlias("kittens", "kit")
* .add( Restrictions.like("kit.name", "Iz%") )
* .list();
* </pre>
* You may specify projection and aggregation using <tt>Projection</tt>
* instances obtained via the factory methods on <tt>Projections</tt>.
* <pre>
* List cats = session.createCriteria(Cat.class)
* .setProjection( Projections.projectionList()
* .add( Projections.rowCount() )
* .add( Projections.avg("weight") )
* .add( Projections.max("weight") )
* .add( Projections.min("weight") )
* .add( Projections.groupProperty("color") )
* )
* .addOrder( Order.asc("color") )
* .list();
* </pre>
*
* @see Session#createCriteria(java.lang.Class)
* @see org.hibernate.criterion.Restrictions
* @see org.hibernate.criterion.Projections
* @see org.hibernate.criterion.Order
* @see org.hibernate.criterion.Criterion
* @see org.hibernate.criterion.Projection
* @see org.hibernate.criterion.DetachedCriteria a disconnected version of this API
* @author Gavin King
*/
There is a query statement that returns the maximum value, minimum value, and average value. To implement this type of query using jpa, you need to use mutiselect
Add the following template in BaseDao
public Object[] mutiselect(Specification<T> specification){
Session session = getSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
Root<T> root = query.from(tClass);
Predicate predicate = specification.toPredicate(root,query,cb);
if(predicate != null){
query.where(predicate);
}
return session.createQuery(query).getSingleResult();
}
Test code
@Test
public void testMutiSelect(){
Object[] object = new ContentInfoDao().mutiselect(new BaseDao.Specification<ContentInfo>() {
@Override
public Predicate toPredicate(Root<ContentInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
query.multiselect(cb.count(root.get("id")),cb.max(root.get("id")),cb.avg(root.get("id")),root.get("id"));
return null;
}
});
System.out.println(Arrays.toString(object));
}
sql
Hibernate:
select
count(contentinf0_.id) as col_0_0_,
max(contentinf0_.id) as col_1_0_,
avg(contentinf0_.id) as col_2_0_,
contentinf0_.id as col_3_0_
from
content_info contentinf0_
[107229, 107431, 53808.1468, 184]
After hibenate 5.2, it is recommended to use the CriteriaQuery interface in java.persistence.criteria in hibernate-jpa