Spring data jpa 多表查询(三:多对多关系动态条件查询)

来源:互联网 发布:软件日记 编辑:程序博客网 时间:2024/05/17 23:24

上一章说了,一对多关系,动态条件查询,这章开始说多对多关系模型


1.A  和 B (n : n)意思就是多对多,下面开始在模型中,建立关系

@Entity

class A 

{

@Column("唯一性标识,主键等等")

String id;


@Column("name = name")

String name;


@ManyToMany(mappedBy="aList")

List<B> bList;

}


@Entity

class B

{

@Column("唯一性标识,主键等等")

String id;


@Column("name = name")

String name;



@ManyToMany()

@JoinTable(name="a2b" ,joinColumns=@JoinColumn(name="b_id"),inverseJoinColumns=@JoinColumn(name="a_id"))

List<A> aList;

}


建好之后,解释下,:A 模型中定义了mappedBy,意思是,A 是 A和B多对多的维护段,添加,删除,修改,一般针对A 模型操作即可,当然也可以从B,只不过,稍微复杂些,此处不再多说。

B 模型中,定义了 中间维护表,指定了表名叫 a2b,并且在 表中,定义了a_id ,b_id, 来标识 A和B多对多关系维护表。

前两张动态条件查询,也适用于现在,因此不再多谢,

只需要一条语句来表名他们之间的关系:

Join<A,B> BJoin = root.join(root.get("bList",JoinType.Left);


这条关系,就已经包含了,把a2b 中间表的查询,包含在里面,大家可以,junit时候,断点查看打印的sql语句


当然,我当时遇到的,是在这基础上,还得加上一层关系,即,C -> A ->B  即:C 和 A 是一对多。A 和B 多对多、

建立的关系如下:

主体是C 

因此root 代表的就是C


Join<C,A> aJoin = root.join(root.get("aList"),JoinType.Left);

Join<A,B> bJoin = aJoin.join("bList",JoinType.Left);

此时,关系就建立好,想带C 。A。B的参数都可以带进来


root 接  C 的参数

aJoin 接 A 的参数

bJoin 接 B 的参数


再次声明一点,JPA ,不支持右连接查询,当然这只是我调研的结果,因为JPA 认为没有父哪来的子,必须从左开始,当然除了内连接。


因此,如果某些业务 需要查询从子开始,JPA 直接查询不到,但是可以换个思路去解决。例如以下需求


更换下上面的模型关系


A ->B -> C

1->n ->n


针对A 传入一个id,查出B 和 C,并且是分页查询,加 动态条件

对于我们来说,只要关系建立好了,动态条件也就好写了。

一般分页,针对 最小单元进行分页,也就是我们的C 做分页

条件如下:a_id 是固定的参数,其次B中的name,c中的name 都是 动态的


因此我的思路是这样的:

1.根据a_id ,查出多个 B

2.根据多个B 查出 B和C 关联表中的C中的id,

3.最后 把C 中的id 查出来作为条件带入C中,即可查出 关联的C


实现的伪代码如下:

Page<C> findC(Pageable pageable,ParamDTO dto ,String a_id)

{

此时主体是C,因此root代表的是C


//Specification ,此处省略,可以参考前两章内容


//1.根据a_id 查出多个B

CriterQuery<B> bQuery = criteraBuilder.createQuery(B.class);

Root<B> root1 = bQuery.from(B.class);


predicateList.add(criteriaBuilder.equal(root1.get("a"),a_id));


//如果有B中的动态参数,即在这里写

if(null != bName)

{

predicateList.add(criteriaBuilder.equal(root1.get("name"),bName));

}


bQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicate.size()])));

//查出了B 的集合

List<B> bList = em.createQuery(bQuery).getResultList();


//上面的criteraBuilder,criteriaQuery,em, root,都已经省略,在上一章可以找到。


下面将List<B> 转换下 B 的id


List<String> ids = new ArrayList<String>();

for(B b:bList)

 {

  ids.add(b.get(id))


这时候,再建立 B 和C 的关系

Join<C,B> bJoin = root.join("bList");

predicateList.add(bJoin.get("id").in(ids));


意思就是  B 和C 建立了 内连接,然后,B 的id 带入,就查出了 C


这里用到了 in  方法,不需要用到criterialBuilder, 到此,jpa的查询,基本上结束,有问题可以留言


}


总结:JPA如果把模型关系理清,sql  的确不怎么需要我们去维护,还是很方便的。还有JPA中的模型之间的懒加载,我还没说,


下一章,开始 说说懒加载













原创粉丝点击