上一章说了,一对多关系,动态条件查询,这章开始说多对多关系模型
1.A 和 B (n : n)意思就是多对多,下面开始在模型中,建立关系
@Entity
class A
{
@Column("唯一性标识,主键等等")
String id;
@Column("name = name")
String name;
@ManyToMany(mappedBy="aList")
List 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 aList;
}
建好之后,解释下,:A 模型中定义了mappedBy,意思是,A 是 A和B多对多的维护段,添加,删除,修改,一般针对A 模型操作即可,当然也可以从B,只不过,稍微复杂些,此处不再多说。
B 模型中,定义了 中间维护表,指定了表名叫 a2b,并且在 表中,定义了a_id ,b_id, 来标识 A和B多对多关系维护表。
前两张动态条件查询,也适用于现在,因此不再多谢,
只需要一条语句来表名他们之间的关系:
Join BJoin = root.join(root.get("bList",JoinType.Left);
这条关系,就已经包含了,把a2b 中间表的查询,包含在里面,大家可以,junit时候,断点查看打印的sql语句
当然,我当时遇到的,是在这基础上,还得加上一层关系,即,C -> A ->B 即:C 和 A 是一对多。A 和B 多对多、
建立的关系如下:
主体是C
因此root 代表的就是C
Join
Join 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,因此root代表的是C
//Specification ,此处省略,可以参考前两章内容
//1.根据a_id 查出多个B
CriterQuery bQuery = criteraBuilder.createQuery(B.class);
Root 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 bList = em.createQuery(bQuery).getResultList();
//上面的criteraBuilder,criteriaQuery,em, root,都已经省略,在上一章可以找到。
下面将List 转换下 B 的id
List
for(B b:bList)
{
ids.add(b.get(id))
}
这时候,再建立 B 和C 的关系
Join
predicateList.add(bJoin.get("id").in(ids));
意思就是 B 和C 建立了 内连接,然后,B 的id 带入,就查出了 C
这里用到了 in 方法,不需要用到criterialBuilder, 到此,jpa的查询,基本上结束,有问题可以留言
}
总结:JPA如果把模型关系理清,sql 的确不怎么需要我们去维护,还是很方便的。还有JPA中的模型之间的懒加载,我还没说,
下一章,开始 说说懒加载