Use hibernate para implementar la función de interfaz JpaSpecificationExecutor en spring-data-jpa

La versión de Hibernate utilizada en este artículo es 5.2.12.Final

Funciones de la interfaz JpaSpecificationExecutor que deben implementarse (excepto 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);
}

Dependencia necesaria

<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>

Archivo de configuración 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();
    }


}

Dos clases de entidad

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;
    }
}

Los siguientes son el Sort y PageRequest necesarios para implementar 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);
    }

}

prueba

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);
    }

El sql generado es el siguiente

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

Si la entidad A está asociada con la entidad B muchos a uno o uno a uno, consulte la entidad A si necesita usar una columna en la entidad B como condición, puede directamente root.get ("a"). Obtener ("columna"). Por ejemplo, en este artículo, UsrUserArticle está asociado con ContentInfo uno a uno. Si desea usar authour en ContentInfo como una consulta condicional, puede usar el siguiente código

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 es el siguiente

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

Si la entidad A y la entidad B tienen una relación de muchos a muchos o de uno a muchos y necesita usar una columna del lado de muchos para la consulta condicional, solo puede usar la consulta de unión jpa (uno a uno, muchos -to-one también puede usar la consulta de combinación) aquí Use la consulta de combinación uno a uno como ejemplo, básicamente lo mismo que muchos a muchos uno a muchos

el código se muestra a continuación

@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 es el siguiente

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

Si desea ordenar por el campo contentInfo asociado

@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

Página de nota de código Num 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: Antes de hibernate5.2, la interfaz Criteria en el paquete org.hibernate en hibernate-core se puede usar más, su javadoc puede ver claramente su uso.

/**
 * <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
 */

Hay una declaración de consulta que devuelve el valor máximo, el valor mínimo y el valor promedio. Para implementar este tipo de consulta usando jpa, debe usar mutiselect

Agregue la siguiente plantilla en 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();
    }

Código de prueba

@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]

Después de hibenate 5.2, se recomienda utilizar la interfaz CriteriaQuery en java.persistence.criteria en hibernate-jpa

Supongo que te gusta

Origin blog.csdn.net/name_is_wl/article/details/81315852
Recomendado
Clasificación