本文使用的Hibernate版本是 5.2.12.Final
需要实现的JpaSpecificationExecutor 接口功能(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);
}
需要的依赖
<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>
配置文件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();
}
}
两个实体类
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;
}
}
下面是实现findAll需要的Sort 和 PageRequest
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);
}
}
测试
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);
}
生成的sql如下
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
如果实体A 多对一或一对一关联这实体B 查询实体A 如需要使用实体B 中的某列作为条件 可以直接 root.get("a").get("column")。例如本文中UsrUserArticle 一对一关联着ContentInfo 如果要使用ContentInfo中的authour作为条件查询 则可以如下代码所示
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 如下
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
如果实体A 与实体B 存在多对多 或者 一对多的关系 且需要使用多的一方的某列进行条件查询 则只能使用 jpa join 查询(一对一、多对一 也可以使用join查询)这里使用 一对一的join查询为例,基本与多对多 一对多相同
代码如下
@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如下
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
如果想用关联的contentInfo 的字段排序
@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
代码 注意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:在hibernate5.2以前使用更多的可能是 hibernate-core中org.hibernate包中的Criteria接口 通过其javadoc可以清楚的看到它的使用方法
/**
* <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
*/
在其中有一个返回 最大值、最小值、平均值的查询语句,使用jpa实现这种类型的查询需要使用mutiselect
在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
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]
hibenate 5.2后推荐使用 hibernate-jpa 中的 java.persistence.criteria中的 CriteriaQuery接口