场景描述
假设模仿健康体检的项目场景,体检的各个项目称为检查项,多个检查项能够组成一个体检组,例如普通检查组包括了身高、体重、血压等等的体检项。同时多个检查组能够组成一个检查套餐。
三者之间的关系是多对多的关系,同一个检查项可以在不同的检查组,同一个检查组可以在不同的检查套餐。
实现效果
通过给出一个检查套餐的id值,能够查出其包含的所有检查组,同时根据这些检查组能够查出每个检查组里面的检查项的详细信息,就是对两重的多对多关系的查询。
前期准备
根据场景的描述,先准备体检项、体检组、体检套餐的POJO类,对应的持久层的配置文件。这里采用的是MyBatis作为持久层框架,通过编写Dao的xml配置文件来实现对数据库的操作。
列出了检查项、检查组和套餐的数据表表名和类的名称。
检查项 | 检查组 | 套餐 | |
---|---|---|---|
数据库表名 | tab_inspectitem | tab-inspectgroup | tab_setmeal |
POJO类 | InspectItem | InspectGroup | Setmeal |
*Dao.xml | InspectItemDao.xml | InspectGroupDao.xml | SetmealDao.xml |
检查项、检查组和套餐的中间表的名称。
tab_inspectgroup_inspectItem #检查项与检查组关联的中间表
tab_setmeal_inspectgroup #检查项与检查组关联的中间表
POJO的InspectItem 类
import java.io.Serializable;
/**
* 检查项
*/
public class InspectItem implements Serializable {
private Integer id;//主键
private String code;//项目编码
private String name;//项目名称
private String sex;//适用性别
private String age;//适用年龄(范围),例如:20-50
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
InspectGroup类
import java.io.Serializable;
import java.util.List;
/**
* 检查组
*/
public class InspectGroup implements Serializable {
private Integer id;//主键
private String code;//编码
private String name;//名称
private String sex;//适用性别
private List<InspectItem > inspectItems;//一个检查组合包含多个检查项
public List<InspectItem > inspectItems() {
return inspectItems;
}
public void setInspectItems(List<InspectItem> inspectItems) {
this.inspectItems= inspectItems;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
Setmeal类
import java.io.Serializable;
import java.util.List;
/**
* 体检套餐
*/
public class Setmeal implements Serializable {
private Integer id;
private String name;
private String code;
private String sex;//套餐适用性别:0不限 1男 2女
private String age;//套餐适用年龄
private List<InspectGroup> inspectGroups;//体检套餐对应的检查组,多对多关系
public List<InspectGroup> getInspectGroups() {
return inspectGroups;
}
public void setInspectGroups(List<InspectGroup> inspectGroups) {
this.inspectGroups = inspectGroups;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
实现过程
根据要达到的要求,通过service层调用dao层的方法,可以根据Setmeal的id来查找套餐的详细内容,Setmeal的属性包含了一个装有InspectGroup类的list集合,而且InspectGroup类中也包含了一个装有InspectItem类的list集合。
这一连串的查找都是通过传入一个Setmeal的id来触发的。
假设Setmeal的service层调用了SetmealDao的
findById()
方法。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.gochen.dao.SetmealDao">
<resultMap id="BaseResultMap" type="com.gochen.pojo.Setmeal">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="code" property="code"/>
<result column="sex" property="sex"/>
<result column="age" property="age"/>
</resultMap>
<!--
collection定义关联集合类型的属性的封装规则
ofType:指定集合里面元素的类型
-->
<resultMap id="findByIdResultMap" type="com.gochen.pojo.Setmeal" extends="BaseResultMap">
<collection property="inspectGroups" javaType="ArrayList" ofType="com.gochen.pojo.InspectGroup"
column="id"
select="com.gochen.dao.InspectGroupDao.findInspectGroupById"></collection>
</resultMap>
<select id="findById" parameterType="int" resultMap="findByIdResultMap">
select * from t_setmeal where id = #{id}
</select>
</mapper>
因为存在着多对多的关系,同时也要查出所有的数据,所以不能单单用resultType来决定返回值的类型,所以要定义自己的返回值的结果集,即使用了resultMap。
将resultMap映射为
findByIdResultMap
,在
findByIdResultMap
中通过
extends属性
继承了Setmeal的基础
BaseResultMap
来查找Setmeal其他属性的值。
在
findByIdResultMap
中的属性
column="id"
,将list集合中的
InspectGroup
的id传到属性select中描述的
InspectGroupDao.findInspectGroupById
来查找InspectGroup的详细内容。
因为
findInspectGroupById()
方法来自InspectGroupDao,所以看InspectGroupDao.xml的配置信息:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.gochen.dao.InspectGroupDao">
<resultMap id="BaseResultMap" type="com.gochen.pojo.InspectGroup">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="code" property="code"/>
<result column="sex" property="sex"/>
</resultMap>
<resultMap id="findByIdResultMap" type="com.gochen.pojo.InspectGroup">
<collection property="inspectItems" javaType="ArrayList" ofType="com.gochen.pojo.InspectItem"
column="id"
select="com.gochen.dao.InspectItemDao.findInspectItemById"></collection>
</resultMap>
<select id="findInspectGroupById" parameterType="int" resultMap="findByIdResultMap">
select * from t_inspectgroup where id in (select inspectgroup_id from t_setmeal_inspectgroup where setmeal_id = #{id})
</select>
</mapper>
在InspectGroupDao.xml中的查找方法是SetmealDao.xml指定的方法,这时id就会传进去,也就是
检查组的id
,进而查找其装有InspectItem类的list集合里面的id,然后传到
InspectItemDao.findInspectItemById()
的方法中,其调用的流程和SetmealDao.xml调用的过程一样,这里就不赘述了。
最后就到InspectItemDao.xml配置信息了:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.gochen.dao.InspectItemDao">
<select id="findInspectItemById" parameterType="int" resultType="com.gochen.pojo.InspectItem">
select * from t_inspectitem where id in (select inspectitem_id from t_inspectgroup_inspectitem where inspectgroup_id = #{id})
</select>
</mapper>
到这里,检查项已经是最小项了,所以在InspectItemDao.xml中只要实现
findInspectItemById()
方法就行了。