文章目录
1.概述
在此前的应用中,我们设计一个实体类对应一个数据库的表。在查找记录的时候,我们在mapper.xml的select标签中使用resultType属性来指定需要进行返回的实体类对象,myBatis会自动完成表字段与实体类成员变量之间的映射关系。
- 如下一个Teacher表对应一个Teacher实体类
public class Teacher {
private int id; //老师编号
private String name; //老师姓名
public Teacher() {
}
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"id2=" + id2 +
", name2='" + name2 + '\'' +
'}';
}
}
- 通过指定resultType,myBatis进行自动映射(要求数据表字段名与实体类成员变量名一一对应)。如id字段的值则通过setId()方法赋给id成员变量。
<select id="selectById" parameterType="int" resultType="Teacher">
select *
from teacher
where id = #{param1};
</select>
2.实现多表查询的方式
但当需要进行多表查询的时候,即查询的结果包含了多个表的内容,使用上述的一个实体类对应一个数据表的方式难以获取所有的结果。如下,我们需要在查找Teacher信息的同时把Teacher的Student信息也一并查出。或则在查找Student的同时把Student的Teacher信息也一起查出。
private int id; //老师编号
private String name; //老师姓名
private List<Student> studentList; //学生列表
private int id; //学生编号
private String name; //学生姓名
private int age; //学生年龄
private int tid; //老师编号
private Teacher teacher; //老师信息
为了实现多表查询有以下三种方式:
2.1.使用业务装配
在service层组装两次查询的结果,如下查出student记录后,再遍历结果在遍历的过程中查出相应的teacher记录。
SqlSession session = MyBatisUtil.getSession();
StudentMapper sm = session.getMapper(StudentMapper.class);
List<Student> list = sm.selectByInfo(pi);
TeacherMapper tm = session.getMapper(TeacherMapper.class);
for (Student s : list) {
Teacher t = tm.selectById(s.getTid());
s.setTeacher(t);
}
2.2. 使用Auto Mapping
对多个表进行连接查询,然后用别名进行映射。如t.id起别名为teacher.id,则myBatis自动寻找student实体类中的teacher变量并调用其setId()方法进行赋值。
<select id="selectAll" resultType="com.bear.sxt.pojo.Student">
select
t.id `teacher.id`,
t.name `teacher.name`,
s.id id,
s.name name,
s.age age,
s.tid tid
from student s left join teacher t on t.id = s.tid;
</select>
2.3.使用resultMap标签
利用resultMap标签可以构建任意的映射关系。
2.3.1.相关标签
- id标签:主键映射
- result标签:非主键字段映射
- association标签:单个对象映射
- collection标签:多个对象映射
2.3.2. 相关属性
- column:数据库表中字段名
- property:实体类中成员变量的名称
通过column和property,即使字段名与变量名不一样也可以完成映射
2.3.3.使用select属性进行额外查询
将原本在业务层中进行装配的查询逻辑移到Mapper.xml中进行。
- N+1查询:查找学生记录(包含了一个teacher,用association)
<resultMap id="studentMap" type="com.bear.sxt.pojo.Student">
<!--这些一一对应的字段可以省略,mybatis会采用auto mapping的方式自行对应-->
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<!--由于tid需要作为参数进行额外的查询,如果这里不写myBatis只会进行一次result.tid到association.tid的映射
这样会导致association中的查询不准确,所以这里一定不能省略-->
<result column="tid" property="tid"/>
<!--association标签的作用是进行额外的查询,select为所执行的查询标签,column为需要作为参数传入的字段-->
<association property="teacher" select="com.bear.sxt.mapper.TeacherMapper.selectById" column="tid"/>
</resultMap>
<select id="selectAll" resultMap="studentMap">
select *
from student
</select>
- 集合查询:查找老师记录(包含了多个student,使用collection)
<resultMap id="teacherMap" type="com.bear.sxt.pojo.Teacher">
<!--主键使用id配置映射-->
<id column="id" property="id"/>
<!--其他字段使用result配置映射-->
<result column="name" property="name"/>
<!--collection标签的作用是进行额外的查询(和association类似,一个返回列表,一个返回单个对象),select为所执行的查询标签,column为需要作为参数传入的字段-->
<collection property="studentList" select="com.bear.sxt.mapper.StudentMapper.selectByTid" column="id"/>
</resultMap>
<select id="selectAll" resultMap="teacherMap">
select *
from teacher;
</select>
2.3.4 连接查询
- 2.3.3中可以使用连接查询查找老师的记录,这样就不需要额外的查询语句了。
- 如果使用的是collection标签则使用ofType标签指明容器元素类型,如果使用的是association标签则使用javaType标签表明对象的类型。
<resultMap id="teacherMap2" type="com.bear.sxt.pojo.Teacher">
<!--当存在collection时mybatis会自动将重复的tid合并为一条记录-->
<!--当不存在collection时,mybatis不会合并重复tid的记录-->
<id column="tid" property="id2"/>
<result column="tname" property="name2"/>
<!--由于连接查询可以查到student表中的内容,所以这里可以直接进行映射,而不像selectById中使用额外查询-->
<collection property="studentList" ofType="com.bear.sxt.pojo.Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>
<select id="selectAll" resultMap="teacherMap2">
select
t.id tid,
t.name tname,
s.id sid,
s.name sname,
s.age sage
from teacher t left join student s on t.id = s.tid;
</select>