失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > jpa多表联查动态_解决 JPA 多表动态查询

jpa多表联查动态_解决 JPA 多表动态查询

时间:2019-10-02 12:24:19

相关推荐

jpa多表联查动态_解决 JPA 多表动态查询

前言

由于公司一直在使用 JPA 作为 ORM 框架,因此分配到需要多表复杂查询或动态查询都很头大。很多人对 JPA 抱有偏见,比如 JPA 只能处理简单的单表查询。下面总结下使用过的几种方法,前几种简单略过。

EntityManager

主要代码:Queryquery=entityManager.createNativeQuery(sql);

Listlist=query.setFirstResult(start).setMaxResults(end).getResultList();

Iteratoriterator=list.iterator();

ListobjList;while(iterator.hasNext()){

Object[]o=(Object[])iterator.next();

Objobj=newObj();

obj.setId(String)o[1];

....//各种类型转换塞值

objList.add(obj);

}

总结:sql 拼接麻烦,手动取对象数组相当麻烦,当sql 字段顺序变了之后,每个取值都需要变化。

使用 Spring 提供的 JdbcTemplate

主要代码:Listlist=jdbcTemplate.query(sql.toString(),newBeanPropertyRowMapper<>(Obj.class));

总结:相比第一种方法简直舒服多了,BeanPropertyRowMapper 可以自动完成映射,也可以自定义实现特殊类型转换,不过自带的已基本够用。另外还支持下划线转驼峰。最后还要写sql,拼代码。

Predicate+Join

单表动态分页查询用 Predicate 就能做到,Join 是多表查询的关键。下面用简单的一对一来做例子@Entity(name="tb_apple")@DatapublicclassApple{@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)privateIntegerid;privateStringname;privateBigDecimalweight;@Enumerated(EnumType.STRING)privateColorEnumcolor;privateDatecreateTime;

}@Entity(name="tb_person")@DatapublicclassPerson{@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)privateIntegerid;privateStringname;@OneToOne

@JoinColumn(name="apple_id")privateAppleapple;

}

Repository接口 除了继承 JpaRepository 之外还需额外继承JpaSpecificationExecutor,有兴趣的可以点进去看看方法。publicinterfacePersonRepositoryextendsJpaRepository,JpaSpecificationExecutor{

}

这里动态查询已Person的name 和 所持有apple 的name 为例:@ComponentpublicclassPersonService{@Autowired

privatePersonRepositorypersonRepository;publicPagefindAll(Stringname,StringappleName,Integerpage,Integersize){//这里可在Pageable里构建Sort用来排序

Pageablepageable=PageRequest.of(page-1,size);

Pagehousings=personRepository.findAll((root,criteriaQuery,criteriaBuilder)

->getPredicate(name,appleName,root,criteriaBuilder),pageable);returnhousings;

}privatePredicategetPredicate(Stringname,StringappleName,Rootroot,CriteriaBuildercriteriaBuilder){

Listlist=Lists.newArrayList();if(StringUtils.isNotEmpty(name)){

list.add(criteriaBuilder.like(root.get("name").as(String.class),"%"+name+"%"));

}if(StringUtils.isNotEmpty(appleName)){

Joinjoin=root.join("apple",JoinType.LEFT);

list.add(criteriaBuilder.like(join.get("name").as(String.class),"%"+appleName+"%"));

}

Predicate[]p=newPredicate[list.size()];returncriteriaBuilder.and(list.toArray(p));

}

}

这样完成了多表动态分页查询。

最后

为 JPA 正名!~

值得一说的我样例用的 Spring Boot 的版本为 2.0.1.RELEASE,因此以下的问题可能是由于新的Spring Boot 版本提高了 JPA 的版本所导致的。PageRequest 的构造函数被标记为 @deprecated ,因此我用了静态方法of,我也觉得这种方式更好

在写单元测试的时候发现repository.findById()返回的类型是Optional,嚯嚯嚯

原本使用的repository.findOne()方法的参数变成了 Example,Example 的例子文档很多

作者:StephenRo

链接:/p/8046233c0178

如果觉得《jpa多表联查动态_解决 JPA 多表动态查询》对你有帮助,请点赞、收藏,并留下你的观点哦!

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