700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Spring Data JPA 从入门到精通~JpaSpecificationExecutor示例

Spring Data JPA 从入门到精通~JpaSpecificationExecutor示例

时间:2022-02-19 02:52:51

相关推荐

Spring Data JPA 从入门到精通~JpaSpecificationExecutor示例

新建两个实体

@Entity(name = "UserInfoEntity")@Table(name = "user_info", schema = "test")public class UserInfoEntity implements Serializable {@Id@Column(name = "id", nullable = false)private Integer id;@Column(name = "first_name", nullable = true, length = 100)private String firstName;@Column(name = "last_name", nullable = true, length = 100)private String lastName;@Column(name = "telephone", nullable = true, length = 100)private String telephone;@Column(name = "create_time", nullable = true)private Date createTime;@Column(name = "version", nullable = true)private String version;@OneToOne(optional = false,fetch = FetchType.EAGER)@JoinColumn(referencedColumnName = "id",name = "address_id",nullable = false)@Fetch(FetchMode.JOIN)private UserReceivingAddressEntity addressEntity;......}@Entity@Table(name = "user_receiving_address", schema = "test")public class UserReceivingAddressEntity implements Serializable {@Id@Column(name = "id", nullable = false)private Integer id;@Column(name = "user_id", nullable = false)private Integer userId;@Column(name = "address_city", nullable = true, length = 500)private String addressCity;......}

UserRepository 需要继承 JpaSpecificationExecutor

public interface UserRepository extends JpaSpecificationExecutor<UserInfoEntity> { }

调用者 UserInfoManager 的写法

我们演示一下直接用 lambda 使用 Root<T> 和 CriteriaBuilder 做一个简单的不同条件的查询和链表查询。

@Componentpublic class UserInfoManager {@Autowiredprivate UserRepository userRepository;public Page<UserInfoEntity> findByCondition(UserInfoRequest userParam,Pageable pageable){return userRepository.findAll((root, query, cb) -> {List<Predicate> predicates = new ArrayList<Predicate>();if (StringUtils.isNoneBlank(userParam.getFirstName())){//liked的查询条件predicates.add(cb.like(root.get("firstName"),"%"+userParam.getFirstName()+"%"));}if (StringUtils.isNoneBlank(userParam.getTelephone())){//equal查询条件predicates.add(cb.equal(root.get("telephone"),userParam.getTelephone()));}if (StringUtils.isNoneBlank(userParam.getVersion())){//greaterThan大于等于查询条件predicates.add(cb.greaterThan(root.get("version"),userParam.getVersion()));}if (userParam.getBeginCreateTime()!=null&&userParam.getEndCreateTime()!=null){//根据时间区间去查询 predicates.add(cb.between(root.get("createTime"),userParam.getBeginCreateTime(),userParam.getEndCreateTime()));}if (StringUtils.isNotBlank(userParam.getAddressCity())) {//联表查询,利用root的join方法,根据关联关系表里面的字段进行查询。predicates.add(cb.equal(root.join("addressEntityList").get("addressCity"), userParam.getAddressCity()));}return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();}, pageable);}}//可以仔细体会上面这个案例,实际工作中应该大部分都是这种写法,就算扩展也是百变不离其中。

我们再来看一个不常见的复杂查询的写法,来展示一下 CriteriaQuery 的用法(作者已经强烈不推荐了哦,和上面比起来太不优雅了)。

public List<MessageRequest> findByConditions(String name, Integer price, Integer stock) { messageRequestRepository.findAll((Specification<MessageRequest>) (itemRoot, query, criteriaBuilder) -> {//这里用 List 存放多种查询条件,实现动态查询List<Predicate> predicatesList = new ArrayList<>();//name 模糊查询,like 语句if (name != null) {predicatesList.add(criteriaBuilder.and(criteriaBuilder.like(itemRoot.get("name"), "%" + name + "%")));}// itemPrice 小于等于 <= 语句if (price != null) {predicatesList.add(criteriaBuilder.and(criteriaBuilder.le(itemRoot.get("price"), price)));}//itemStock 大于等于 >= 语句if (stock != null) {predicatesList.add(criteriaBuilder.and(criteriaBuilder.ge(itemRoot.get("stock"), stock)));}//where() 拼接查询条件query.where(predicatesList.toArray(new Predicate[predicatesList.size()]));//返回通过 CriteriaQuery 拼装的 Predicatereturn query.getRestriction();});}

而没有 Spring Data JPA 封装之前,如果想获得此三个对象 Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder,老式 Hibernate 的写法如下(PS:强烈不推荐哦,虽然现在也支持,只是让大家知道了解一下。):

@Autowired //导入entityManagerprivate EntityManager entityManager;//创建CriteriaBuilder安全查询工厂,CriteriaBuilder是一个工厂对象,安全查询的开始.用于构建JPA安全查询.CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();//创建CriteriaQuery安全查询主语句//CriteriaQuery对象必须在实体类型或嵌入式类型上的Criteria 查询上起作用。CriteriaQuery<Item> query = criteriaBuilder.createQuery(Item.class);//Root 定义查询的From子句中能出现的类型Root<Item> itemRoot = query.from(Item.class);

我们再来看一个利用 CriteriaQuery 例子,其实大家可以扩展一下思路,就是 Hibernate 那套在这里面都支持,不过作者还是建议代码越简单越好。

List<UserSpuFavoriteEntity> result = userSpuFavoriteDao.findAll((Root<UserSpuFavoriteEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb)->{query.where(cb.and(cb.equal(root.get("userName"), userName),cb.isFalse(root.get("isDelete"))));query.orderBy(cb.desc(root.get("updateTime")));return query.getRestriction();});

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。