文章目录
前言
MyBatis是一个非常优秀的持久层框架,从工作开始基本所有接触的项目使用的都是MyBatis框架,个人感觉它的优点就是轻量级,易配置,sql自由,结果集映射功能强大。除了使用起来舒服,MyBatis的整体设计理念也是很优秀的,清晰的分层设计,对于设计模式的使用,也是值得学习和思考的,虽然自己目前对于其中一些设计理念还难以理解。
当前想详细介绍和总结一下自己常用到的级联查询和动态sql几个场景。虽然比较简单,但是每次写的时候都要查资料,所以自己记录一下。
业务相关数据模型
一个简单的教师-班级-学生 关系数据模型

级联查询示例
-
业务场景
根据上述数据模型,需求是查询某个班级的班级名称、班主任名和所有的学生名。
-
定义返回数据模型
定义需求所需要数据的VO实体
public class ClassInfoVO { private Long id; private String className; private String headTeacherName; private List<String> studentName; /** * getter/setter */ } -
定义mapper接口
public interface TClassMapper { ClassInfoVO getDetail(@Param("id") Long id); } -
映射文件
<?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.learn.mybatiscrud.mapper.TClassMapper"> <resultMap id="classInfoMapper" type="com.learn.mybatiscrud.vo.ClassInfoVO"> <id property="id" column="id"/> <result property="className" column="name"/> <association property="headTeacherName" column="head_teacher_id" select="com.learn.mybatiscrud.mapper.TeacherMapper.getTeacherName"></association> <collection property="studentName" column="id" select="com.learn.mybatiscrud.mapper.TStudentMapper.getStudentList"></collection> </resultMap> <select id="getDetail" resultMap="classInfoMapper"> select * from t_class where id=#{id} </select> </mapper>分析:
resultMap可以实现将查询结果映射为较复杂的结果对象(ClassInfoVO),其中resultMap中的property对应的就是ClassInfoVO的属性,colum对应的是数据表字段名称,即select * from中的 *部分。
其中association和collection标签分别表示一对一和一对多的查询,分别有三个属性,property,colum,select。这里怎么理解呢,既然是叫结果集映射嘛,本质就是将数据库查询的结果和定义的VO字段一一映射起来,property代表的还是VO字段,只不过这里colum值和property值没直接映射起来,而是多做了一次查询,查询的方法是另一个mapper接口方法,接口参数值就是colum的值,然后再把这次查询的结果和property映射起来。 -
resultMap的select方法和映射文件
mapper接口
public interface TeacherMapper { String getTeacherName(@Param("id") Long id); }public interface TStudentMapper { /** * 通过班级ID查询该班级所有学生名称 * @param classId * @return */ List<String> getStudentList(Long classId); }映射文件:
TeacherMapper.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.learn.mybatiscrud.mapper.TeacherMapper"> <select id="getTeacherName" resultType="String"> select name from t_teacher where id=#{id} </select> </mapper>TStudent.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.learn.mybatiscrud.mapper.TStudentMapper"> <select id="getStudentList" resultType="String"> select name from t_student where class_id=#{classId} </select> </mapper>这部分就非常简单了,通过t_class表中的head_teacher_id,从t_teacher表中查出教师名称,这个是一对一的查询。通过t_class表中的id,从t_student表中查出属于该班级所有学生的名称,结果就是一个List,这是一对多的查询。
动态sql(foreach)使用示例
动态sql是MyBatis一大特色,MyBatis 采用功能强大的基于 OGNL 的表达式来实现动态sql,用了很多简练易用的标签屏蔽sql拼接细节,真的很舒服。常用的标签有 if test, where之类的。我只想记录一下foreach标签的使用,因为老是忘记。
来个最简单的示例吧,查询某些老师的信息,就是一个简单的 in 查询。
-
定义返回数据模型
public class Teacher { private Long id; private String name; private String title; /** * getter setter * / } -
mapper接口
public interface TeacherMapper { List<Teacher> getTeacherInfo(List<Long> ids); } -
映射文件
<?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.learn.mybatiscrud.mapper.TeacherMapper"> <select id="getTeacherInfo" resultType="com.learn.mybatiscrud.entity.Teacher"> select * from t_teacher where id in <foreach collection="list" item="item" index="index" open="(" separator="," close=")"> #{item} </foreach> </select> </mapper>
collection:代表要循环的对象
item:代表当前迭代对象
index:代表当前迭代索引(即 0,1,2 …)
open,close:代表循环开始和结束插入的符号
separator:表示每次循环插入的符号。
值得说明的是collection里面的值,是根据mapper接口确定的,如果接口传入List对象,并且没有给方法参数指定key值,那么collection的值默认是list,如果接口传入的是数组,那么collection的值默认是array。
但是如果在mapper接口方法指定了key值,那么collection的值就是key值。
如:
public interface TeacherMapper {
List<Teacher> getTeacherInfo(@Param("ids") List<Long> ids);
}
则 collection=“ids”
后记
MyBatis还有其他很多知识需要学习,如缓存,事务等,但是感觉最需要学习的整个框架的设计思想,各模块的内聚和耦合,恰恰这个最难的。

本文介绍了MyBatis中的级联查询(association, collection)和动态SQL(foreach)的简单使用示例,包括教师-班级-学生的关系模型、一对多查询映射配置以及动态SQL在in查询中的应用。"
109362220,8527557,MySQL高级知识入门:配置文件与存储引擎解析,"['数据库理论', 'MySQL', '存储引擎', 'SQL']
492





