前言
在实际开发中,数据库表之间往往存在关联关系,多表关联查询是常见需求
MyBatis 作为优秀的持久层框架,提供了灵活的关联查询处理方式
本文将聚焦 MyBatis 中一对一、一对多及多对多关联查询的核心实现,帮助开发者快速掌握通过映射配置处理表间关联的方法
个人主页:艺杯羹
1. MyBatis关联查询
MyBatis的关联查询分为一对一关联查询和 一对多关联查询
- 查询对象时,将关联的另一个对象查询出来,就是一对一关联查询。
- 查询对象时,将关联的另一个对象的集合查询出来,就是一对多关联查询。
例如有学生类和班级类:
一个学生对应一个班级,也就是学生类中有一个班级属性,这就是一对一关系
一个班级对应多个学生,也就是班级类中有一个学生集合属性,这就是一对多关系
实体类设计如下:
public class Student { private int sid; private String name; private int age; private String sex; private Classes classes; // 省略getter/setter/toString } public class Classes { private int cid; private String className; private List<Student> studentList; // 省略getter/setter/toString }
2. 一对一关联查询
查询学生时,将关联的一个班级对象查询出来,就是一对一关联查询
关联对象类标签:association
创建持久层接口
public interface StudentMapper { List<Student> findAll(); }
创建映射文件
-- 自定义映射关系 <resultMap id="studentMapper" type="com.yibeigen.pojo.Student"> <!-- 主键列 --> <id property="sid" column="sid"></id> <!-- 普通列 --> <result property="name" column="name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> <!-- 一对一对象列 property:属性名 column:关联列名 javaType:对象类型--> 封装 <association property="classes" column="classId" javaType="com.yibeigen.pojo.Classes"> <!-- 关联对象主键列 --> <id property="cid" column="cid"></id> <!-- 关联对象普通列 --> <result property="className" column="className"></result> </association> </resultMap> <!-- 多表查询,级联查询学生和其班级 --> <select id="findAll" resultMap="studentMapper"> select * from student left join classes on student.classId = classes.cid; </select>
配置文件注册映射文件
<mappers> <package name="com.yibeigen.mapper"/> </mappers>
测试一对一关联查询
InputStream is = null; SqlSession session = null; @Before public void before() throws IOException { is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(is); session = factory.openSession(); } @After public void after() throws IOException { session.close(); is.close(); } @Test public void testFindAllStudent(){ StudentMapper studentMapper = session.getMapper(StudentMapper.class); List<Student> all = studentMapper.findAll(); all.forEach(System.out::println); }
3. 一对多关联查询
查询班级时,将关联的学生集合查询出来,就是一对多关联查询
封装:collection
创建持久层接口
public interface ClassesMapper { List<Classes> findAll(); }
创建映射文件
<resultMap id="classesMapper" type="com.itbaizhan.pojo.Classes"> <id property="cid" column="cid"></id> <result property="className" column="className"></result> <!-- 集合列 property:属性名 column:关联列名 ofType:集合的泛型 --> <collection property="studentList" column="classId" ofType="com.yibeigen.pojo.Student"> <id property="sid" column="sid"></id> <result property="name" column="name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> </collection> </resultMap> <!-- 多表查询,级联查询班级和它的学生 --> <select id="findAll" resultMap="classesMapper"> select * from classes left join student on classes.cid = student.classId; </select>
测试一对多关联查询
@Test public void testFindAllClasses() { ClassesMapper classesMapper = session.getMapper(ClassesMapper.class); List<Classes> all = classesMapper.findAll(); all.forEach(System.out::println); }
4. 多对多关联查询
MyBatis多对多关联查询本质就是两个一对多关联查询
例如有老师类和班级类:
一个老师对应多个班级,也就是老师类中有一个班级集合属性
一个班级对应多个老师,也就是班级类中有一个老师集合属性
实体类设计如下:
public class Teacher { private Integer tid; private String tname; private List<Classes> classes; // 省略getter/setter/toString } public class Classes { private Integer cid; private String className; private List<Student> studentList; private List<Teacher> teacherList; // 省略getter/setter/toString }
在数据库设计中,需要建立中间表,双方与中间表均为一对多关系
接下来测试查询老师时,将关联的班级集合查询出来
创建持久层接口
public interface TeacherMapper { List<Teacher> findAll(); }
创建映射文件
<resultMap id="teacherMapper" type="com.yibeigen.pojo.Teacher"> <id column="tid" property="tid"></id> <result column="tname" property="tname"></result> <collection property="classes" column="tid" ofType="com.yiebeigen.pojo.Classes"> <id column="cid" property="cid"></id> <result column="className" property="className"></result> </collection> </resultMap> <select id="findAll" resultMap="teacherMapper"> select * from teacher left join classes_teacher on teacher.tid = classes_teacher.tid left join classes on classes_teacher.cid = classes.cid </select>
测试多对多关联查询
@Test public void testFindAllTeacher() { TeacherMapper teacherMapper = session.getMapper(TeacherMapper.class); List<Teacher> all = teacherMapper.findAll(); all.forEach(System.out::println); }
5. 总结