日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring-Data-JPA 动态查询黑科技

發布時間:2024/9/30 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring-Data-JPA 动态查询黑科技 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在開發中,用到動態查詢的地方,所有的查詢條件包括分頁參數,都會被封裝成一個查詢類XxxQuery

比如說上一篇中的Item

那么ItemQuery就像這樣

@Data public class ItemQuery {private Integer itemId;//id精確查詢 =private String itemName;//name模糊查詢 like//價格查詢private Integer itemPrice;// 價格小于'條件' < }

那現在問題來了,如何去標識這些字段該用怎樣的查詢條件連接呢,還要考慮到每個查詢類都可以通用.


可以用字段注解,來標識字段的查詢連接條件

//用枚舉類表示查詢連接條件 public enum MatchType {equal, // filed = value//下面四個用于Number類型的比較gt, // filed > valuege, // field >= valuelt, // field < valuele, // field <= valuenotEqual, // field != valuelike, // field like valuenotLike, // field not like value// 下面四個用于可比較類型(Comparable)的比較greaterThan, // field > valuegreaterThanOrEqualTo, // field >= valuelessThan, // field < valuelessThanOrEqualTo, // field <= value; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface QueryWord {// 數據庫中字段名,默認為空字符串,則Query類中的字段要與數據庫中字段一致String column() default "";// equal, like, gt, lt...MatchType func() default MatchType.equal;// object是否可以為nullboolean nullable() default false;// 字符串是否可為空boolean emptiable() default false; }

好了,現在我們可以改造一下ItemQuery了

@Data public class ItemQuery {@QueryWord(column = "item_id", func = MatchType.equal)private Integer itemId;@QueryWord(func = MatchType.like)private String itemName;@QueryWord(func = MatchType.le)private Integer itemPrice; }

現在,我們還需要去構造出查詢時的動態條件,那就創建一個所有查詢類的基類BaseQuery,我們把分頁的條件字段放在基類里.

/*** 所有查詢類的基類*/ @Getter @Setter @NoArgsConstructor @AllArgsConstructor public abstract class BaseQuery<T> {// start from 0protected int pageIndex = 0;protected int pageSize = 10;/*** 將查詢轉換成Specification* @return*/public abstract Specification<T> toSpec();//JPA分頁查詢類public Pageable toPageable() {return new PageRequest(pageIndex, pageSize);}//JPA分頁查詢類,帶排序條件public Pageable toPageable(Sort sort) {return new PageRequest(pageIndex, pageSize, sort);}//動態查詢and連接protected Specification<T> toSpecWithAnd() {return this.toSpecWithLogicType("and");}//動態查詢or連接protected Specification<T> toSpecWithOr() {return this.toSpecWithLogicType("or");}//logicType or/andprivate Specification<T> toSpecWithLogicType(String logicType) {BaseQuery outerThis = this;return (root, criteriaQuery, cb) -> {Class clazz = outerThis.getClass();//獲取查詢類Query的所有字段,包括父類字段List<Field> fields = getAllFieldsWithRoot(clazz);List<Predicate> predicates = new ArrayList<>(fields.size());for (Field field : fields) {//獲取字段上的@QueryWord注解QueryWord qw = field.getAnnotation(QueryWord.class);if (qw == null)continue;// 獲取字段名String column = qw.column();//如果主注解上colume為默認值"",則以field為準if (column.equals(""))column = field.getName();field.setAccessible(true);try {// nullableObject value = field.get(outerThis);//如果值為null,注解未標注nullable,跳過if (value == null && !qw.nullable())continue;// can be emptyif (value != null && String.class.isAssignableFrom(value.getClass())) {String s = (String) value;//如果值為"",且注解未標注emptyable,跳過if (s.equals("") && !qw.emptiable())continue;}//通過注解上func屬性,構建路徑表達式Path path = root.get(column);switch (qw.func()) {case equal:predicates.add(cb.equal(path, value));break;case like:predicates.add(cb.like(path, "%" + value + "%"));break;case gt:predicates.add(cb.gt(path, (Number) value));break;case lt:predicates.add(cb.lt(path, (Number) value));break;case ge:predicates.add(cb.ge(path, (Number) value));break;case le:predicates.add(cb.le(path, (Number) value));break;case notEqual:predicates.add(cb.notEqual(path, value));break;case notLike:predicates.add(cb.notLike(path, "%" + value + "%"));break;case greaterThan:predicates.add(cb.greaterThan(path, (Comparable) value));break;case greaterThanOrEqualTo:predicates.add(cb.greaterThanOrEqualTo(path, (Comparable) value));break;case lessThan:predicates.add(cb.lessThan(path, (Comparable) value));break;case lessThanOrEqualTo:predicates.add(cb.lessThanOrEqualTo(path, (Comparable) value));break;}} catch (Exception e) {continue;}}Predicate p = null;if (logicType == null || logicType.equals("") || logicType.equals("and")) {p = cb.and(predicates.toArray(new Predicate[predicates.size()]));//and連接} else if (logicType.equals("or")) {p = cb.or(predicates.toArray(new Predicate[predicates.size()]));//or連接}return p;};}//獲取類clazz的所有Field,包括其父類的Fieldprivate List<Field> getAllFieldsWithRoot(Class<?> clazz) {List<Field> fieldList = new ArrayList<>();Field[] dFields = clazz.getDeclaredFields();//獲取本類所有字段if (null != dFields && dFields.length > 0)fieldList.addAll(Arrays.asList(dFields));// 若父類是Object,則直接返回當前Field列表Class<?> superClass = clazz.getSuperclass();if (superClass == Object.class) return Arrays.asList(dFields);// 遞歸查詢父類的field列表List<Field> superFields = getAllFieldsWithRoot(superClass);if (null != superFields && !superFields.isEmpty()) {superFields.stream().filter(field -> !fieldList.contains(field)).//不重復字段forEach(field -> fieldList.add(field));}return fieldList;} }

在BaseQuery里,就通過toSpecWithAnd() toSpecWithOr()方法動態構建出了查詢條件.

那現在ItemQuery就要繼承BaseQuery,并實現toSpec()抽象方法

@Data public class ItemQuery extends BaseQuery<Item> {@QueryWord(column = "item_id", func = MatchType.equal)private Integer itemId;@QueryWord(func = MatchType.like)private String itemName;@QueryWord(func = MatchType.le)private Integer itemPrice;@Overridepublic Specification<Item> toSpec() {return super.toSpecWithAnd();//所有條件用and連接} }

當然肯定還有其他不能在BaseQuery中構建的查詢條件,那就在子類的toSpec()實現中添加,

比如下面的例子,ItemQuery條件改成這樣

@QueryWord(column = "item_id", func = MatchType.equal) private Integer itemId; @QueryWord(func = MatchType.like) private String itemName; //價格范圍查詢 private Integer itemPriceMin; private Integer itemPriceMax;

那其他條件就可以在toSpec()添加,這樣就可以很靈活的構建查詢條件了

@Override public Specification<Item> toSpec() {Specification<Item> spec = super.toSpecWithAnd();return ((root, criteriaQuery, criteriaBuilder) -> {List<Predicate> predicatesList = new ArrayList<>();predicatesList.add(spec.toPredicate(root, criteriaQuery, criteriaBuilder));if (itemPriceMin != null) {predicatesList.add(criteriaBuilder.and(criteriaBuilder.ge(root.get(Item_.itemPrice), itemPriceMin)));}if (itemPriceMax != null) {predicatesList.add(criteriaBuilder.and(criteriaBuilder.le(root.get(Item_.itemPrice), itemPriceMax)));}return criteriaBuilder.and(predicatesList.toArray(new Predicate[predicatesList.size()]));}); }

調用:

@Test public void test1() throws Exception {ItemQuery itemQuery = new ItemQuery();itemQuery.setItemName("車");itemQuery.setItemPriceMax(50);itemQuery.setItemPriceMax(200);Pageable pageable = itemQuery.toPageable(new Sort(Sort.Direction.ASC, "itemId"));Page<Item> all = itemRepository.findAll(itemQuery.toSpec(), pageable); }

現在這個BaseQuery和QuertWord就可以在各個動態查詢處使用了,只需在查詢字段上標注@QueryWord注解,

然后實現BaseQuery中的抽象方法toSpec(),通過JpaSpecificationExecutor接口中的這幾個方法,就可以實現動態查詢了,是不是很方便.

public interface JpaSpecificationExecutor<T> {T findOne(Specification<T> var1);List<T> findAll(Specification<T> var1);Page<T> findAll(Specification<T> var1, Pageable var2);List<T> findAll(Specification<T> var1, Sort var2);long count(Specification<T> var1); }

總結

以上是生活随笔為你收集整理的Spring-Data-JPA 动态查询黑科技的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美做爰全过程免费看 | a黄色片| 国产毛片视频 | 337p亚洲精品色噜噜狠狠 | 97久久精品| 激情黄色小说网站 | 青青草视频偷拍 | 四虎网站最新网址 | 久久久久久久国产视频 | 欧美国产大片 | 欧美性色黄 | 十八岁世界在线观看高清免费韩剧 | 中国少妇乱子伦视频播放 | 三级大片在线观看 | a级免费视频 | 亚洲天堂中文字幕在线 | 日本网站在线播放 | 亚洲福利av | 夜夜骚视频 | www日韩在线观看 | 久久精品国产清自在天天线 | 欧美肉大捧一进一出免费视频 | 一级特黄性色生活片 | xxxx日本免费| 欧美亚洲国产另类 | 日日麻批 | 中国亚洲女人69内射少妇 | 婷婷的五月天 | 人妻少妇一区二区 | 樱桃成人精品视频在线播放 | 综合伊人久久 | 国产微拍精品一区 | 亚洲欧美国产精品专区久久 | 亚洲一区二区三区在线免费观看 | 日本一级一片免费视频 | 国产美女精品久久久 | 色多多视频在线观看 | 一区二区免费在线视频 | 波多野结衣一区二区三区免费视频 | 福利视频二区 | 久久免费黄色 | 久久精品在线视频 | 影音先锋啪啪 | 久久久久性 | 中国一级特黄录像播放 | 毛片av免费 | 精品国产免费观看 | 欧美大片免费在线观看 | 亚洲黄色成人网 | 青春草在线视频免费观看 | 欧美成人国产精品一区二区 | 日韩操 | 国产又黄又猛的视频 | 国产成人亚洲综合a∨婷婷 台湾a级片 | 国产精品一区二区三区四区五区 | 免费视频网站在线观看入口 | 91麻豆精品一区二区三区 | 日韩成人免费在线 | 国产精品成人网站 | 久久天天东北熟女毛茸茸 | 成人午夜sm精品久久久久久久 | youjizzxxx69 | 99热91| 久草大| 中国一级特黄毛片 | 综合欧美亚洲 | 日韩一级黄| 国产xxxxx在线观看 | 欧美国产日本在线 | 91超碰在线 | 日韩免费久久 | 亚洲综合免费观看高清完整版 | 亚洲一区在线免费观看 | 你懂的在线播放 | 国产精品毛片一区视频播 | 无码精品国产一区二区三区 | 中文字幕二区在线观看 | 91文字幕巨乱亚洲香蕉 | 98自拍视频| 国产精品免费视频一区 | 欧美 日韩 人妻 高清 中文 | 阿v视频免费在线观看 | 高跟鞋调教—视频|vk | 青青青视频免费观看 | 亚洲成年人 | 欧美 日韩 国产 成人 在线观看 | 成人毛片观看 | 日韩经典在线观看 | 国产乱子伦精品无码专区 | 人妻射精一区二区 | 国产日韩欧美综合 | 色哟哟入口国产精品 | 四季av一区二区三区免费观看 | 人人狠狠综合久久亚洲 | 免费成人看视频 | 成人av手机在线 | 国产一级特黄视频 | 四季av在线一区二区三区 | 草碰在线视频 |