Spring data jpa 多表查询(一:单表动态条件查询)

1.前言:由于项目用到了jpa,所以开始对jpa进行探究,本来,简单的模型,增删改查,继承
JpaRepository,就可以了,但是 遇到复杂的一对多,和多对多,分页等动态查询条件,就头疼了,下面就开始我的研究
 
(声明下哈:下面的是我做项目中摸索的,所以写的是伪代码,当中有些不对的,还请大家见谅)
 
 
 
 
1.环境:spring cloud + boot + idea + jpa
 
自己的接口继承JpaRepository 上,再继承 JpaSpecificationExecutor,在这个接口中,有几个方法
a.T findOne(Specification<T> var1)
b.List<T> findAll(Specification<T> var1)
c.Page<T> findAll(Specification<T> var1, Pageable var2)
d.List<T> findAll(Specification<T> var1, Sort var2);
e.long count(Specification<T> var1);
一般只用到动态条件的查询,就会使用 a 和 b 的方法, 分页查询 用到 b
下面有个场景,
1:一对多:(A 1:n B)
class A
{
  @Column("name = a_name")
  String aName;
  @OneToMany("mappedBy = a")
  List<B> bList;
}
class B
{
  @Column("name = b_name")
  String bName;
 
  @ManyToOne
  @JoinColumn("name = a_id")
  A a;
}
注解:1.mappedBy = a,是在B 中定义的a,其次,这样就不会再生成一张维护表。2.JoinColumn,会在B生产的表中,多一个a的外键叫 a_id 
这时候,两张表的关系建成后,就开始动态条件查询:
1.建立AInterface:
Page<A> findAll(Pageable pageable,ADTO adto);
注解:ADTO ,是传过来的条件封装成DTO,条件少的可以直接传字符串.
2.建立实现类AInterfaceImpl implements AInterface
public Page<A> findAll(Pageable pageable,ADTO adto)
{
//1.针对传过来的参数进行非空过滤,这边就忽略写了
//2.利用ExampleMatcher 方法
//如果你查询的条件,是等于的话,如下 第一行即可,不然即第二行:
ExampleMatcher matcher = ExampleMatcher.matching();
or
ExampleMatcher matcher = ExampleMatcher.matching()
	.withMatcher("name  过滤不为空的参数",ExampleMatcher.GenericPropertyMatchers.contains());//这是针对name,进行模糊查询,多个继续往下添加
	
//继续
Example<A> AExample = Example.of(A,matcher);
Page<A> aPage = ARepository.findAll(AExample,pageable);
这样即可:这种的方法只适用于单表,并且有几个局限性
1.传进来的参数,如果是 "",空字符串,必须转换为null,Example 才会忽略对它的查询,不然,Example会把它当做条件去查
2.只适合单表查询,一旦出现多表关联,就无法使用,除非,你用了视图,把多张表的查询,建立成一个视图,在视图上进行查找
3.针对Example的具体细节,大家可以百度,在这里我就不多说了。
   
}
既然Example 不能满足我们多表的查询,相信,大家也不太会使用,因此,接下来介绍的方法比较实用了
继续实现我们的 AInterface 
AInterfaceImpl implements AInterface
public Page<A> findAll(Pageable pageable,ADTO adto)
{
//1.对adto 参数进行获取,
String name = dto.getName();
//2.声明一个
List<Predicate> predicateList = new ArrayList<Predicate>();
Predicate 是用于动态条件查询,用到的必须对象,
//定义一个 querySpecifi 内部类实现方法,里面封装了表关联和动态条件,Specification 大家可以百度具体的含义,我这边只是说我自己的用法,有些含义,我也不清楚,请见谅哈
     Specification querySpecifi = new Specification<Category>() {
         @Override
          public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder)
{
		//条件判断
		if(null != name)
                 {
   	           
                   predicateList.add(criteriaBuilder.equal(root.get("name"),name));
                   //这里简单解释下,我对上面的关键词和对象解释
                   在 toPredicate 方法中,有三个参数,Root,criteriaQuery,CriteriaBuilder,
                   1.root 是当前的根元素,里面的实现是根据反射技术生成,因此,root.get("A 定义的某个字段名称"),当前指向的就是A模型
                   2.CriteriaQuery ,看名字,知道是个query查询的接口,里面封装了一下几个方法:select,where,groupby,having,orderingby...
                     基本上是用于查询的方法,有条件的,可以进入源码查看。
                   3.CriteriaBuilder,bulider里面也有些封装方法:createQuery,asc,desc,equal,等等,用于对条件进行操作,等于,大于,排序等等
                   
                   因此,上面的语句就是,root.get("name") 就是 A 类中的 name 属性,  criteriaBuilder.equal(root.get("name"),name),就是
                  A类中的name属性  == 所传的name,相等的条件。  然后加入 predicateList。
                  最后,return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
                  
		这句意思就是,predicateList里面的所有条件,都是 and 操作,就类似,where and ...and ...
                我上面定义的是predicateList ,多条件,如果是单个条件,就声明一个 Prediacate predicate = criteriaBuilder.equal(root.get("name"),name) 
		}
         }
         //最后分页结果查询,调用内部类的结果集
         Page<A> aList = aRepository.findAll(querySpecifi,pageable);
         return aList;
      }

   
   
}
文笔有限,请大家多包涵,有问题或者建议,留言哈,
//下一章说下,多对多的关系建立

                
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值