MyBatis基础用法--使用resultMap自定义高级映射规则

目录

resultMap简介

resultMap的用法

id & result

constructor

association

嵌套查询

嵌套结果

collection

嵌套查询

嵌套结果

discriminator


resultMap简介

在前面两篇文章中,我们都是通过使用select元素的resultType属性指定查询结果的返回值类型,来让MyBatis自动将查询结果集封装成我们希望的类型进行返回。

resultType属性非常有用,但在返回结果类型比较复杂的情况下却无能为力,为此,MyBatisselect元素中还为我们提供了另外一个resultMap属性,用于引用一个使用<resultMap/>元素定义好的自定义结果集映射规则。

<resultMap/>算是MyBatis中最重要、最强大的元素了,它可以让你比使用JDBC调用结果集省掉90%的代码,也可以让你做许多JDBC不支持的事。 事实上,编写类似的对复杂语句联合映射的代码也许会需要上千行。resultMap的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们的关系。  

resultMap的用法

<resultMap/>元素有很多子元素: 

<constructor>		 /*用来将查询结果作为参数注入到实例的构造方法中*/
	<idArg />	 /*标记结果作为 ID*/

	<arg />		 /*标记结果作为普通参数*/

</constructor>
<id/>			 /*一个ID结果,标记结果作为 ID*/
<result/>		 /*一个普通结果,JavaBean的普通属性或字段*/
<association>		 /*关联其他的对象*/
</association>
<collection>		 /*关联其他的对象集合*/
</collection>
<discriminator>	         /*鉴别器,根据结果值进行判断,决定如何映射*/
	<case></case>	 /*结果值的一种情况,将对应一种映射规则*/
</discriminator>

在一个<resultMap/>元素中,这些子元素出现的先后顺序是有严格规定的,它们从前到后依次是:constructor-->id --> result--> association-->collection -->discriminator。  

id & result

<id/><result/>resultMap中最基本的映射内容,它们都可以将查询结果中一个单独列的值映射为返回结果对象中的简单数据类型(字符串,整型,双精度浮点数,日期等)的单独属性或字段。这两者之间的唯一不同是id 表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射) 。 

<!-- 返回javaBean对象 -->
<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<result column="STUDENT_GENDER" property="studentGender" />
	<result column="STUDENT_BIRTHDAY" property="studentBirthday" />
	<result column="STUDENT_AGE" property="studentAge" />
</resultMap>
<!-- 返回Map对象 -->
<resultMap type="map" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" javaType="long"/>
	<result column="STUDENT_NAME" property="studentName" javaType="string"/>
	<result column="STUDENT_GENDER" property="studentGender" javaType="string"/>
	<result column="STUDENT_BIRTHDAY" property="studentBirthday" javaType="date"/>
	<result column="STUDENT_AGE" property="studentAge" javaType="int"/>
</resultMap>

<id/><result/>都支持以下几个属性: 

属性描述
column从数据库中查询到的结果集的列名或列别名
property将 column属性指定的列结果映射到对象的哪个属性
javaType列结果在对象中所对应的Java数据类型,返回类型为Map时需指定
jdbcType列结果在数据库中所支持的JDBC 类型
typeHandler所使用的类型处理器

为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型。

BITFLOATCHARTIMESTAMPOTHERUNDEFINED
TINYINTREALVARCHARBINARYBLOBNVARCHAR
SMALLINTDOUBLELONGVARCHARVARBINARYCLOBNCHAR
INTEGERNUMERICDATELONGVARBINARYBOOLEANNCLOB
BIGINTDECIMALTIMENULLCURSORARRAY

constructor

使用<constructor/>元素可以在对象实例化时,将查询到结果集作为参数注入到实例的构造方法中,以实现对实例化对象的特殊处理。

例如,为了防止由于数据库学生表中的年龄字段长期未更新,而导致查询出来的学生年龄信息不准确,我们希望查询学生信息时根据学生的生日计算出学生的年龄,而不再直接从数据库中获取学生的年龄信息。

首先在学生实体类StudentEntity中增加如下构造方法:

private static final SimpleDateFormat yearFormat = new SimpleDateFormat(
			"yyyy");
public StudentEntity(Long studentId, Date studentBirthday) {
	super();
	this.studentId = studentId;
	if (null != studentBirthday) {
        	this.studentBirthday = studentBirthday;
		int startYear = Integer
				.parseInt(yearFormat.format(studentBirthday));
		int nowYear = Integer.parseInt(yearFormat.format(new Date()));
		this.studentAge = nowYear - startYear;
	}
}

相应的Mapper配置如下。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<constructor>
		<idArg column="STUDENT_ID" javaType="java.lang.Long" />
		<arg column="STUDENT_BIRTHDAY" javaType="java.util.Date" />
	</constructor>
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<result column="STUDENT_GENDER" property="studentGender" />
</resultMap>
<select id="selectStudentById" resultMap="studentResultMap">
	select * from
	tbl_student where
	STUDENT_ID =
	#{studentId}
</select>

<constructor/>元素的<idArg/><arg/>除了支持示例中的columnjavaType属性,还支持以下几个属性:jdbcTypetypeHandlerselectresultMapname,其中的name属性从3.4.3版本起开始引入,用来指定该在构造方法中形参的名字。
注意:使用<constructor/>元素在构造方法中初始化的参数若使用resultMap的其他子元素进行映射,则构造方法为对象实例赋予的属性值将被覆盖。

association

<association/>元素用于处理查询结果中关联其他对象的情况,比如:一个学生属于一个班级,我们在查询一个学生的信息时,想要把他所在的班级也一并查出。

public class StudentEntity {

	private Long studentId;

	private String studentName;

	private ClassEntity studentClass;
	
	//此处省略get和set方法

}

MyBatis提供了两种不同的方式用来处理这种对象关联查询:嵌套查询和嵌套结果。

嵌套查询

所谓嵌套查询,指的是通过执行另外一个 SQL 映射语句来返回所关联的对象类型。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<association column="CLASS_ID" property="studentClass"
		select="selectClassById" javaType="org.mybatis.entity.ClassEntity" />
</resultMap>
<select id="selectStudentById" resultMap="studentResultMap">
	select * from
	tbl_student where
	STUDENT_ID =
	#{studentId}
</select>
<resultMap type="org.mybatis.entity.ClassEntity" id="classResultMap">
	<id column="CLASS_ID" property="classId" />
	<result column="CLASS_NAME" property="className" />
</resultMap>
<select id="selectClassById" resultMap="classResultMap">
	select * from
	tbl_class
	where
	CLASS_ID =
	#{classId}
</select>

注:<association/>元素可以通过columnPrefix属性可以祛除查询结果内列名的指定前缀。

嵌套结果

所谓嵌套结果,指的是通过联表查询将所需的所有字段内容先查询出来,再通过级联属性映射来创建复杂类型的结果对象。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<result column="CLASS_ID" property="studentClass.classId" />
	<result column="CLASS_NAME" property="studentClass.className" />
</resultMap>
<sql id="studentAndClassFields">
	s.STUDENT_ID AS STUDENT_ID,
	s.STUDENT_NAME AS STUDENT_NAME,
	c.CLASS_ID AS CLASS_ID,
	c.CLASS_NAME AS CLASS_NAME
</sql>
<select id="selectStudentById" resultMap="studentResultMap">
	SELECT
	<include refid="studentAndClassFields"></include>
	FROM
	tbl_student s
	LEFT OUTER JOIN
	tbl_class c ON s.CLASS_ID=c.CLASS_ID
	WHERE
	s.STUDENT_ID=#{studentId}
</select>

此时的resultMap还可以写为如下两种形式。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<association property="studentClass" javaType="org.mybatis.entity.ClassEntity">
		<id column="CLASS_ID" property="classId" />
		<result column="CLASS_NAME" property="className" />
	</association>
</resultMap>
<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<association property="studentClass" resultMap="classResultMap">
	</association>
</resultMap>
<resultMap type="org.mybatis.entity.ClassEntity" id="classResultMap">
	<id column="CLASS_ID" property="classId" />
	<result column="CLASS_NAME" property="className" />
</resultMap>

collection

<collection/>元素用于处理查询结果中关联其他对象集合的情况,比如:一个班级包含多个学生,我们在查询一个班级的信息时,想要把这个班级里的学生集合也一并查出。

public class ClassEntity {

	private Long classId;

	private String className;

	private List<StudentEntity> students;

	//此处省略get和set方法
}

嵌套查询

<resultMap type="org.mybatis.entity.ClassEntity" id="classResultMap">
		<id column="CLASS_ID" property="classId" />
		<result column="CLASS_NAME" property="className" />
		<collection column="CLASS_ID" property="students" javaType="list"
			select="listStudentsByClass">
		</collection>
	</resultMap>

	<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
		<id column="STUDENT_ID" property="studentId" />
		<result column="STUDENT_NAME" property="studentName" />
	</resultMap>

	<select id="selectClassById" resultMap="classResultMap">
		select * from
		tbl_class
		where
		CLASS_ID =
		#{classId}
	</select>

	<select id="listStudentsByClass" parameterType="long"
		resultMap="studentResultMap">
		select * from
		tbl_student
		where
		CLASS_ID =
		#{classId}
	</select>

嵌套结果

<resultMap type="org.mybatis.entity.ClassEntity" id="classResultMap">
	<id column="CLASS_ID" property="classId" />
	<result column="CLASS_NAME" property="className" />
	<collection column="CLASS_ID" property="students" javaType="list"
		ofType="org.mybatis.entity.StudentEntity">
		<id column="STUDENT_ID" property="studentId" />
		<result column="STUDENT_NAME" property="studentName" />
	</collection>
</resultMap>
<sql id="classAndStudentsFields">
	c.CLASS_ID AS CLASS_ID,
	c.CLASS_NAME AS CLASS_NAME,
	s.STUDENT_ID AS STUDENT_ID,
	s.STUDENT_NAME AS STUDENT_NAME
</sql>
<select id="selectClassById" parameterType="long" resultMap="classResultMap">
	SELECT
	<include refid="classAndStudentsFields"></include>
	FROM tbl_class c
	LEFT JOIN tbl_student s ON c.CLASS_ID=s.CLASS_ID
	WHERE
	c.CLASS_ID=#{classId}
</select>

此时的resultMap也可以写为如下形式。

<resultMap type="org.mybatis.entity.ClassEntity" id="classResultMap">
	<id column="CLASS_ID" property="classId" />
	<result column="CLASS_NAME" property="className" />
	<collection property="students" javaType="list"
		ofType="org.mybatis.entity.StudentEntity" resultMap="studentResultMap">
	</collection>
	</resultMap>
<resultMap type="org.mybatis.entity.StudentEntity" id="studentResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
</resultMap>

discriminator

<discriminator/>元素很像Java语言中的switch 语句,允许用户根据查询结果中指定字段的不同取值来执行不同的映射规则,比如:在查询一个班级的学生信息时,如果学生是男生则将其年龄信息一并查出,如果学生是女生则不查询其年龄信息而是将班级信息一并查出。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentSResultMap">
	<discriminator column="STUDENT_GENDER" javaType="string">
		<case value="男" resultMap="maleResultMap"/>
		<case value="女" resultMap="femaleResultMap"/>
	</discriminator>
</resultMap>
<resultMap type="org.mybatis.entity.StudentEntity" id="maleResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<result column="STUDENT_AGE" property="studentAge" />
</resultMap>
<resultMap type="org.mybatis.entity.StudentEntity" id="femaleResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<association column="CLASS_ID" property="studentClass"
		javaType="org.mybatis.entity.ClassEntity">
		<id column="CLASS_ID" property="classId" />
		<result column="CLASS_NAME" property="className" />
	</association>
</resultMap>

此时的resultMap也可以写为如下形式。

<resultMap type="org.mybatis.entity.StudentEntity" id="studentSResultMap">
	<id column="STUDENT_ID" property="studentId" />
	<result column="STUDENT_NAME" property="studentName" />
	<discriminator column="STUDENT_GENDER" javaType="string">
		<case value="男" resultType="org.mybatis.entity.StudentEntity">
			<result column="STUDENT_AGE" property="studentAge" />
		</case>
		<case value="女" resultType="org.mybatis.entity.StudentEntity">
			<association column="CLASS_ID" property="studentClass"
				javaType="org.mybatis.entity.ClassEntity">
				<id column="CLASS_ID" property="classId" />
				<result column="CLASS_NAME" property="className" />
			</association>
		</case>
	</discriminator>
</resultMap>

注:在使用<resultMap/>元素进行分步查询时,如果需要传递多个参数到关联的查询语句中,可以使用column="{classId=CLASS_ID}"将参数封装到Map进行传参,接收参数的查询语句需将parameterType设置为Map类型。

  • 27
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MyBatis-Plus提供了非常方便的分页查询功能,可以直接使用Page类来进行分页查询。 使用MyBatis-Plus的分页查询,需要进行以下步骤: 1. 引入MyBatis-Plus的依赖:在pom.xml中添加以下依赖: ``` <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> ``` 2. 定义实体类:定义需要进行分页查询的实体类,并使用注解@TableField进行字段映射。 3. 定义Mapper接口:定义Mapper接口,并继承BaseMapper类,继承BaseMapper类后,MyBatis-Plus会自动提供一些基本的CRUD操作。 ``` public interface UserMapper extends BaseMapper<User> {} ``` 4. 分页查询:在Service层中调用分页查询方法,使用Page对象设置分页参数,然后调用selectPage方法进行分页查询。 ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public Page<User> getUserList(int pageNum, int pageSize) { Page<User> page = new Page<>(pageNum, pageSize); return userMapper.selectPage(page, null); } } ``` 如果需要自定义sql分页,可以在xml中使用MyBatis的分页插件进行分页查询。 1. 引入分页插件:在pom.xml中添加以下依赖: ``` <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency> ``` 2. 配置分页插件:在MyBatis的配置文件中配置分页插件。 ``` <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="dialect" value="mysql"/> </plugin> </plugins> ``` 3. 自定义sql分页查询:在xml中使用分页插件的PageHelper.startPage方法进行分页查询。 ``` <select id="getUserList" resultMap="userMap"> select * from user <where> <if test="name != null"> and name like concat('%',#{name},'%') </if> </where> order by id desc </select> ``` ``` @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public PageInfo<User> getUserList(int pageNum, int pageSize, String name) { PageHelper.startPage(pageNum, pageSize); List<User> userList = userMapper.getUserList(name); return new PageInfo<>(userList); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值