Use hibernate to implement the JpaSpecificationExecutor interface function in spring-data-jpa

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&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;autoReconnect=true&amp;failOverReadOnly=false&amp;maxReconnects=20&amp;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

Guess you like

Origin blog.csdn.net/name_is_wl/article/details/81315852