spring jpa 動態查詢(Specification)


//dao層  繼承 擴展倉庫接口JpaSpecificationExecutor (JPA 2引入了一個標准的API
public
interface CreditsEventDao extends JpaRepository<CreditsEventBean, Integer>, JpaSpecificationExecutor<CreditsEventBean>{}

 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/      官方文檔 -- 5.5. Specifications

JpaSpecificationExecutor提供了以下接口:

/**
 * Interface to allow execution of {@link Specification}s based on the JPA criteria API.
 * 
 * @author Oliver Gierke
 */
public interface JpaSpecificationExecutor<T> {

    /**
     * Returns a single entity matching the given {@link Specification}.
     * 返回與給定的{@link規范}匹配的單個實體
     * @param spec
     * @return
     */
    T findOne(Specification<T> spec);

    /**
     * Returns all entities matching the given {@link Specification}.
     * 返回與給定的{@link規范}匹配的所有實體。
     * @param spec
     * @return
     */
    List<T> findAll(Specification<T> spec);

    /**
     * Returns a {@link Page} of entities matching the given {@link Specification}.
     * 返回與給定的{@link規范}匹配的實體的{@link頁面}。
     * @param spec
     * @param pageable
     * @return
     */
    Page<T> findAll(Specification<T> spec, Pageable pageable);

    /**
     * Returns all entities matching the given {@link Specification} and {@link Sort}.
     * 返回與給定的{@link規范}和{@link排序}匹配的所有實體。
     * @param spec
     * @param sort
     * @return
     */
    List<T> findAll(Specification<T> spec, Sort sort);

    /**
     * Returns the number of instances that the given {@link Specification} will return.
     * 返回給定的{@link規范}將返回的實例數量。
     * @param spec the {@link Specification} to count instances for
     * @return the number of instances
     */
    long count(Specification<T> spec);
}
  

我項目上使用到的實例:

public Page<TestBean> specificationFind(Integer size, Integer page, TestBean test) {
        Field[] fields = CreditsEventBean.class.getDeclaredFields(); //通過反射獲取實體類的所有屬性
        Sort sort = new Sort(Direction.ASC, "sort").and(new Sort(Direction.DESC, "cutOffTime"));//排序規則   多條件
        Pageable pageable = new PageRequest(page-1, size, sort);//分頁 return activityDao.findAll(new Specification<CreditsEventBean>() {// Page<T> findAll(Specification<T> spec, Pageable pageable); 分頁加多態查詢 
            @SuppressWarnings("unchecked")//壓制警告
            @Overridepublic Predicate toPredicate(Root<CreditsEventBean> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Map<String, Object> conditions = null;
                try {
                    conditions = BeanUtils.describe(event);//使用Apache的工具類將實體轉換成map
                    conditions.remove("sort");//去掉某些用不到的字段  比如排序字段等
                    conditions.remove("maxPlayers");//                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    e.printStackTrace();
                    System.err.println("specificationFind ---bean轉map出錯");
                }
                List<Predicate> predicates = new ArrayList<>();//存儲查詢語句 for (int i = 0; i < fields.length; i++) {//循環bean的所有屬性
                    fields[i].setAccessible(true);//是否允許訪問
                    String name = fields[i].getName();//獲取屬性名 if(conditions.containsKey(name)) {//查詢這個鍵是否存在與這個屬性中
                        if(ObjectUtils.isEmpty(conditions.get(name))) {//判斷這個鍵的值是否為空
                            continue;//結束本次循環,進入下一次循環
                        }
                        if(name.equals("creditStatus")||name.equals("activityShop")
                                ||name.equals("isShopEvent")||name.equals("isPutaway")) {//這里 等於條件
                            predicates.add(cb.equal(root.get(name), conditions.get(name)));
                
注意:如果查詢的表中有關聯的表,可能會報錯
原因:可能是bean轉map的時候,BeanUtils.describe方法將關聯bean沒取出來,只是取了關聯bean的內存地址並存儲為字符串,導致關聯bean的數據消失

暴力解決方法:
if(name.equals("關聯Bean")) {
                                predicates.add(cb.equal(root.get(name),filed.get關聯Bean()));
                            }else {
                                predicates.add(cb.equal(root.get(name), conditions.get(name)));
                            }
 
         

 

continue;
                        }else if(name.equals("activityStartCreditsDT")||name.equals("activityEndCreditsDT")
                                ||name.equals("creteateTime")||name.equals("cutOffTime")) {// 這里是between條件
                            String value = (String) conditions.get(name);
                            String[] split = value.split(",");//分割
                            predicates.add(cb.between(root.get(name), split[0], split[1]));
                            continue;
    
                        }
                        predicates.add(cb.like(root.get(name), "%"+conditions.get(name)+"%"));// 這里是 模糊 條件          
                    }
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));//返回結果集
            }
        }, pageable);
        
        
        
    }

 CriteriaBuilder主要api:

等!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM