<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在上一篇文章中,我們介紹了QueryByExampleExecutor動態查詢的方法,那麼今天我們來學習JpaSpecificationExecutor的詳細用法。
我們來建立實體類,第一步:建立User類和UserAddress類
// User類 @Data @Entity @NoArgsConstructor @AllArgsConstructor @Builder @ToString(exclude = "address") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String name; private String email; @Enumerated(value = EnumType.STRING) private SexEnum sex; private Integer age; private LocalDateTime createTime; private LocalDateTime updateTime; @OneToMany(mappedBy = "user",fetch = FetchType.EAGER) private List<UserAddress> address; } // Address類 @Entity @Data @Builder @AllArgsConstructor @NoArgsConstructor @ToString(exclude = "user") public class UserAddress { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String address; @ManyToOne(cascade = CascadeType.ALL) private User user; } // 性別列舉類 public enum SexEnum { BOY, GIRL }
第二步:建立UserRepo ,我們繼承JpaSpecificationExecutor介面
public interface UserRepo extends JpaSpecificationExecutor<User> { }
第三步:測試,構造查詢條件
@Test public void test02(){ User userQuery = User.builder() .name("jack") .email("123456@126.com") .sex(SexEnum.BOY) .age(20) .address(Lists.newArrayList(UserAddress.builder().address("shanghai").build())) .build(); List<User> userList = userRepo.findAll(new Specification<User>() { @Override public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicateList = new ArrayList<>(); // name模糊查詢 if(StringUtils.isNotBlank(userQuery.getName())) { predicateList.add(cb.like(root.get("name"),userQuery.getName())); } // sex精準查詢 if(userQuery.getSex()!=null) { predicateList.add(cb.equal(root.get("sex"),userQuery.getSex())); } // age範圍查詢 if(userQuery.getAge()!=null){ predicateList.add(cb.greaterThanOrEqualTo(root.get("age"),userQuery.getAge())); } // 關聯查詢 if(!ObjectUtils.isEmpty(userQuery.getAddress())) { predicateList.add(cb.in(root.join("address").get("address")).value(userQuery.getAddress().stream().map(a->a.getAddress()).collect(Collectors.toList()))); } return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction(); } }); System.out.println(userList); }
SQL執行結果如下:
select user0_.id as id1_4_, user0_.age as age2_4_, user0_.create_time as create_t3_4_, user0_.email as email4_4_, user0_.name as name5_4_, user0_.sex as sex6_4_, user0_.update_time as update_t7_4_ from user user0_ inner join user_address address1_ on user0_.id=address1_.user_id where (user0_.name like ?) and user0_.sex=? and user0_.age>=20 and (address1_.address in (?))
先看原始碼:
public interface JpaSpecificationExecutor<T> { Optional<T> findOne(@Nullable Specification<T> spec); List<T> findAll(@Nullable Specification<T> spec); Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable); List<T> findAll(@Nullable Specification<T> spec, Sort sort); long count(@Nullable Specification<T> spec); boolean exists(Specification<T> spec); }
我們主要來看一下需要實現的方法:toPredicate(xx,xx,xx)
@Nullable Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
偵錯程式碼
我們可以分別看到Root的實現類是RootImpl,CriteriaQuery的實現類是CriteriaQueryImpl,CriteriaBuilder的實現類是CriteriaBuilderImpl。這三個實現類都是由Hibernate實現,也就是說JpaSepcificationExecutor封裝了原本需要我們直接操作Hibernate中Criteria的API。
解釋:這個root就相當於查詢和操作的實體物件的根,我們就可以通過Path get(xx)的方法,來獲取我們想要操作的欄位。
<Y> Path<Y> get(String attributeName);
例如:獲取User實體類中的name欄位
predicateList.add(cb.like(root.get("name"),userQuery.getName()));
這是一個Specific的頂層查詢物件,它包含著查詢的各個部分,比如select、from、where、group by 、Order by、distinct等。提供查詢Root的方法,我們來看一下原始碼:
我們可以在上面的案例中看到query的用法:
return query.where(predicateList.toArray(new Predicate[predicateList.size()])).getRestriction();
我們可以再加一個groupBy的例子看看,如下所示:可以鏈式拼接
return query.where(predicateList.toArray(new Predicate[predicateList.size()])).groupBy(root.get("age")).getRestriction();
執行的SQL如下所示:
CriteriaBuilder是用來構建CritiaQuery的構建物件,其實就相當於條件或者條件組合,並以Predicate的形式返回,基本提供了所有常用的方法。
通過原始碼我們可以看到CriteriaBuilder 提供了and、any等用來查詢條件的組合;還提供了between、equal、exist等用來做查詢條件的查詢。
例如:equal
predicateList.add(cb.equal(root.get("sex"),userQuery.getSex()));
例如:like
predicateList.add(cb.like(root.get("name"),userQuery.getName()));
例如:greaterThanEqualTo
predicateList.add(cb.greaterThanOrEqualTo(root.get("age"),userQuery.getAge()));
解釋: 我們利用equal、like、greaterThanEqualTo 可以返回Predicate,而Predicate又可以組合起來,就構成了複雜的查詢條件,完全滿足日常開發使用。
以上就是Spring Data JPA系列JpaSpecificationExecutor用法詳解的詳細內容,更多關於Spring Data JPA JpaSpecificationExecutor的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45