多表关联查询是软件开发中最常见的应用场景,多表查询需要将数据实体之间的一对多、多对多、一对一的关系的转换为复杂的数据对象。mybaits提供的association和collection元素,通过映射文件构造复杂实体对象,在构造实体过程中,mybaits提供的了嵌套查询和嵌套结果查询两种查询方式,前者通过执行多次SQL语句,并支持延迟加载;后者执行一次SQL语句,通过SQL语句的执行结果构造实体。
掌握嵌套查询的使用
掌握嵌套结果查询的使用
掌握单个实体(association)和实体集合(collection)的使用
以教师和课程呈现的一对一关系为例,验证association元素的使用
以教师和课程呈现的一对一关系为例,验证嵌套查询使用
以教师和课程呈现的一对一关系为例,验证嵌套结果查询使用
以学生和课程呈现的一对多关系为例,验证collection元素的使用
以学生和课程呈现的一对多关系为例,验证嵌套查询使用
以学生和课程呈现的一对多关系为例,验证嵌套结果查询使用
字段名称 | 字段代码 | 数据类型 | 备注 |
学号 | sno | integer | 主键自增 |
学生姓名 | sname | varchar(50) | |
年龄 | sage | integer |
字段名称 | 字段代码 | 数据类型 | 备注 |
工号 | tno | integer | 主键自增 |
教师姓名 | tname | varchar(50) | |
年龄 | tage | integer |
字段名称 | 字段代码 | 数据类型 | 备注 |
课程号 | cno | integer | 主键自增 |
课程名 | cname | varchar(50) | |
学分 | ccredit | integer |
学生选课表(tb_sc)
字段名称 | 字段代码 | 数据类型 | 备注 |
课程号 | cno | integer | 主键自增 |
课程名 | cname | varchar(50) | |
学分 | ccredit | integer |
@Data
public class TeacherEntity {
private Integer tno;
private String tname;
private Integer tage;
}
课程实体文件如下所示
@Data
public class CourseEntity {
private int cno;
private String cname;
private int ccredit;
private TeacherEntity teacher;
}
学生实体类代码如下
@Data
public class StudentEntity {
private Integer sno;
private String sname;
private Integer sage;
private List<CourseEntity> courses;
}
public interface TeacherDao {
TeacherEntity getTeacherByCourse(Integer cno);
}
课程接口文件
public interface CourseDao {
List<CourseEntity> getAllCourse();
List<CourseEntity> getAllCourseByResult();
List<CourseEntity> getCourseByStudentId(Integer sno);
}
学生接口文件
public interface StudentDao {
List<StudentEntity> getAllStudent();
List<StudentEntity> getAllStudent2();
}
展示一对一信息,需要在映射文件中使用association元素
<mapper namespace="com.bjwl.dao8.CourseDao" >
<resultMap id="CoursePojo" type="com.bjwl.pojo8.CourseEntity">
<id property="cno" column="cno">id>
<result property="cname" column="cname">result>
<result property="ccredit" column="ccredit">result>
<association property="teacher" column="cno" fetchType="eager"
javaType="com.bjwl.pojo8.TeacherEntity" select="com.bjwl.dao8.TeacherDao.getTeacherByCourse">association>
resultMap>
<select id="getAllCourse" resultMap="CoursePojo" >
select * from tb_course
select>
mapper>
代码中首先定义了一个resultMap ,建立复杂对象的映射关系,association代表在课程实体(CourseEntity)中有一个教师(teacher)的属性,对应数据类型是教师的实体,二者之间通过列cno关联,数据的获取是通过com.bjwl.dao8.TeacherDao.getTeacherByCourse实现的。其次定义获取全部课程数据使用的方法(getAllCourse)。
定义教师的映射文件(TeacherMapper.xml),在映射文件中定义getTeacherByCourse对应的SQL,代码如下
<mapper namespace="com.bjwl.dao8.TeacherDao" >
<select id="getTeacherByCourse" resultType="com.bjwl.pojo8.TeacherEntity">
select * from tb_teacher where cno = #{cno}
select>
mapper>
测试代码如下
public void test11Nest() throws IOException {
SqlSession sqlSession = BatisUtils.getSqlSessionFactory().openSession();
CourseDao dao = sqlSession.getMapper(CourseDao.class);
List<CourseEntity> courses = dao.getAllCourse();
for (CourseEntity course : courses ){
System.out.println(course.toString());
}
<mapper namespace="com.bjwl.dao8.CourseDao" >
<resultMap id="CoursePojo2" type="com.bjwl.pojo8.CourseEntity">
<id property="cno" column="cno">id>
<result property="cname" column="cname">result>
<result property="ccredit" column="ccredit">result>
<association property="teacher" javaType="com.bjwl.pojo8.TeacherEntity">
<id property="tno" column="tno">id>
<result property="tname" column="tname">result>
<result property="tage" column="tage">result>
association>
resultMap>
<select id="getAllCourseByResult" resultMap="CoursePojo2">
select * from tb_course a left join tb_teacher b on a.cno =b.cno
select>
mapper>
代码中association ,定义返回结果集中列和实体属性的对应关系。测试代码如下图所示
public void test11Result() throws IOException {
SqlSession sqlSession = BatisUtils.getSqlSessionFactory().openSession();
CourseDao dao = sqlSession.getMapper(CourseDao.class);
List<CourseEntity> courses = dao.getAllCourseByResult();
for (CourseEntity course : courses ){
System.out.println(course.toString());
}
}
展示一对多信息,需要在映射文件中使用实体集合(collection)元素,
<mapper namespace="com.bjwl.dao8.StudentDao" >
<resultMap id="studentInfo" type="com.bjwl.pojo8.StudentEntity">
<id property="sno" column="sno">id>
<result property="sname" column="sname">result>
<result property="sage" column="sage">result>
<collection property="courses" column="sno" ofType="com.bjwl.pojo8.CourseEntity"
select="com.bjwl.dao8.CourseDao.getCourseByStudentId">
collection>
resultMap>
<select id="getAllStudent" resultMap="studentInfo">
select * from tb_student
select>
mapper>
代码中首先定义了一个resultMap ,建立复杂对象的映射关系,collection 代表在学生实体中(StudentEntity)中有一个课程(courses)的属性,二者之间通过列sno关联,数据的获取是通过com.bjwl.dao8.CourseDao.getCourseByStudentId实现的。其次定义获取全部课程数据使用的方法(getCourseByStudentId)。
定义课程的映射文件(TeacherMapper.xml),在映射文件中定义getCourseByStudentId对应的SQL,代码如下
<mapper namespace="com.bjwl.dao8.CourseDao" >
<select id="getCourseByStudentId" resultType="com.bjwl.pojo8.CourseEntity">
select * from tb_course a,tb_sc b
where a.cno = b.cno and
b.sno = #{sno}
select>
mapper>
测试代码如下:
public void test1nNest() throws IOException {
SqlSession sqlSession = BatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<StudentEntity> students = dao.getAllStudent();
for (StudentEntity student : students ){
System.out.println(student.toString());
}
}
<mapper namespace="com.bjwl.dao8.StudentDao" >
<resultMap id="studentInfo2" type="com.bjwl.pojo8.StudentEntity">
<id property="sno" column="sno">id>
<result property="sname" column="sname">result>
<result property="sage" column="sage">result>
<collection property="courses" column="sno" ofType="com.bjwl.pojo8.CourseEntity">
<id property="cno" column="cno">id>
<result property="cname" column="cname">result>
<result property="ccredit" column="ccredit">result>
collection>
resultMap>
<select id="getAllStudent2" resultMap="studentInfo2">
SELECT aa.*,bb.* FROM
(SELECT a.`sno`,a.`sname`,a.`sage`,b.`cno`
FROM tb_student a LEFT JOIN tb_sc b ON a.sno = b.`sno`) aa LEFT JOIN tb_course bb
ON aa.cno = bb.`cno`;
select>
测试代码如下:
public void test1nResult() throws IOException {
SqlSession sqlSession = BatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<StudentEntity> students = dao.getAllStudent2();
for (StudentEntity student : students ){
System.out.println(student.toString());
}
}