Mybatis查询之resultMap的使用
使用result的高级功能,一对一映射、一对多映射以及多对多映射
一对一映射对应的标签为association,一对多映射对应的标签为collection
一对一映射使用包装对象实现,例如:要查找学生和班级,但是学生信息以及班级信息在两个类中,可以将班级类型作为一个对象包装进入学生类中
@Data
public class Student {
private Integer id;
private String studentName;
private String studentSex;
private Integer studentClass;
private Integer studentAge;
private ClassEntity classEntity;
}
association和collection二者标签的内部属性基本是一致的,它们的属性介绍如下:
- (常用)property:映射 实体类属性名。
- (常用)column:映射数据库字段名或者其别名(这个别名是数据库起的,如 select username as name)。
- (常用)javaType:映射java类型。
- (常用)jdbcType:映射数据库类型。
- (常用)ofType:映射集合的类型(注意:javaType是用来指定pojo中属性的类型,而ofType指定的是映射到list集合属性中pojo的类型,也就是尖括号的泛型private List users)。
- (常用)select:用于加载复杂类型属性的映射语句的id(全限定名加方法,方法名后面无括号,例如:com.thr.mapper.UserMapper.selectAllUser),它会从column 属性指定的列中检索数据,作为参数传递给目标 select 语句。
- (常用)fetchType:延迟加载,lazy打开延迟加载,eager积极加载。指定属性后,将在映射中忽略全局配置参数lazyLoadingEnabled,使用属性的值。
- resultMap:不使用嵌套模式,而是将此关联的嵌套结果集映射到一个外部的标签中,然后通过 id 进行引入。
- resultSet:指定用于加载复杂类型的结果集名字。
- autoMapping:自动封装,如果数据库字段和javaBean的字段名一样,可以使用这种方式,但是不建议采取,如果非要使用此功能,那就在全局配置中加上mapUnderscoreToCamelCase=TRUE,它会使经典数据库字段命名规则翻译成javaBean的经典命名规则,如:a_column翻译成aColumn。
- columnPrefix:关联多张表查询时,为了使列明不重复,使用此功能可以减少开发量。
- foreignColumn:指定外键对应的列名,指定的列将与父类型中 column 的给出的列进行匹配。
- notNullColumn:不为空的列,如果指定了列,那么只有当字段不为空时,Mybatis才会真正创建对象,才能得到我们想要的值。
- typeHandler:数据库与Java类型匹配处理器(可以参考前面的TypeHandler部分)。
一对一映射
嵌套查询
映射xml语句
<resultMap id="StudentClassMap" type="com.spring.demo.entity.Student">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="student_name" property="studentName" jdbcType="VARCHAR"/>
<result column="student_sex" property="studentSex" jdbcType="VARCHAR"/>
<result column="student_age" property="studentAge" jdbcType="INTEGER"/>
<result column="student_class" property="studentClass" jdbcType="INTEGER"/>
<!--一对一关联对象-->
<!--property:映射实体类属性名字-->
<!--javaType:映射Java类型-->
<association property="classEntity" javaType="com.spring.demo.entity.ClassEntity">
<!--property和column表示映射实体类和其表中字段绑定-->
<!--此处有一个小问题,就是如果id为 <id property="id" column="id"/> 时,会出现查询结果中的id是学生的id,className没有错误-->
<id property="classId" column="class_id"/>
<result property="className" column="class_name"/>
</association>
</resultMap>
<!--查询所有数据-->
<select id="selectStudentClass" resultMap="StudentClassMap">
select * from
student_table s,
class_table c
where
s.student_class = c.class_id
</select>
<!--根据学生id查找其信息-->
<select id="selectStudentClassById" parameterType="java.lang.Integer" resultMap="StudentClassMap">
select * from
student_table s,
class_table c
where
s.student_class = c.class_id
and s.id = #{id}
</select>
分布查询
<!--分布查询-->
<resultMap id="StudentClassMap2" type="com.spring.demo.vo.StudentVo">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="student_name" property="studentName" jdbcType="VARCHAR"/>
<result column="student_sex" property="studentSex" jdbcType="VARCHAR"/>
<result column="student_age" property="studentAge" jdbcType="INTEGER"/>
<result column="student_class" property="studentClass" jdbcType="INTEGER"/>
<!--column为student表中班级字段, property为StudentVo类中班级类名,javaType为班级类,select指定通过id查询班级的接口-->
<association column="student_class" property="classEntity" javaType="com.spring.demo.entity.ClassEntity"
select="com.spring.demo.dao.ClassDAO.selectById"/>
</resultMap>
<select id="selectStudentClassById_" parameterType="java.lang.Integer" resultMap="StudentClassMap2">
select * from
student_table
where
id = #{id}
</select>
// studentVo类
@Data
// 作用是在 json 序列化时忽略 bean 中的一些不需要转化的属性
@JsonIgnoreProperties(value = { "handler" })
public class StudentVo {
private Integer id;
private String studentName;
private String studentSex;
private Integer studentClass;
private Integer studentAge;
private ClassEntity classEntity;
}
总结
分布查询会比嵌套查询多执行几个sql,所以效率上是嵌套查询更好,但是分布查询可以延迟加载(懒加载)
一对多映射
嵌套查询
<resultMap id="ClassStudentMap" type="com.spring.demo.vo.ClassEntityVo">
<id column="class_id" property="classId"/>
<result column="class_name" property="className"/>
<!--一对多映射-->
<!--ofType:指定pojo的类型,为list尖括号内部的泛型-->
<collection property="students" ofType="com.spring.demo.entity.Student">
<id column="id" property="id"/>
<result column="student_name" property="studentName"/>
<result column="student_sex" property="studentSex"/>
<result column="student_age" property="studentAge"/>
<result column="student_class" property="studentClass"/>
</collection>
</resultMap>
<!--查询所有班级学生-->
<select id="selectClassStudent" resultMap="ClassStudentMap">
select * from
class_table c,
student_table s
where
c.class_id = s.student_class
</select>
<!--通过班级id查询班级学生-->
<select id="selectClassStudentById" parameterType="java.lang.Integer" resultMap="ClassStudentMap">
select * from
class_table c,
student_table s
where
c.class_id = s.student_class
and c.class_id = #{classId}
</select>
分布查询
<resultMap id="ClassStudentMap2" type="com.spring.demo.vo.ClassEntityVo">
<id column="class_id" property="classId"/>
<result column="class_name" property="className"/>
<collection column="class_id" property="students" ofType="com.spring.demo.entity.Student"
select="com.spring.demo.dao.StudentDAO.selectByClass"/>
</resultMap>
<!--分布查询,通过班级id查询班级学生-->
<select id="selectClassStudentById_" parameterType="java.lang.Integer" resultMap="ClassStudentMap2">
select * from class_table
where class_id = #{classId}
</select>