MyBatis框架学习:<select>节点中的resultType和resultMap属性

1.为什么要进行resultType或resultMap注解配置

当需要实现的数据访问是查询类型的,在<select>节点中必须配置resultTyperesultMap中的某1个属性(二选一),如果都没有指定,则会出现如下错误:

Caused by: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'cn.tedu.mybatis.UserMapper.count'.  It's likely that neither a Result Type nor a Result Map was specified.

解决因为名称不一致导致MyBatis无法自动封装查询结果的问题

  • 当自定义字段列表时,自定义别名,使得名称保持一致,并且,在<select>节点中使用resultType即可;
  • 当使用星号表示字段列表时,配置<resultMap>以指导MyBatis封装,并且,在<select>节点中使用resultMap应用配置的<resultMap>

2.resultType

其中,resultType指的就是“封装查询结果的数据的类型”,也可以理解为“抽象方法的返回值的类型”,例如可以配置为:

<select id="count" resultType="java.lang.Integer">
	SELECT COUNT(*) FROM t_user
</select>

如果某个查询的抽象方法的返回值是List集合类型的,例如:

List<User> findAll();

在配置<select>resultType属性时,该属性值必须是集合中的元素的类型,例如:

<select id="findAll" resultType="cn.tedu.mybatis.User">
    SELECT * FROM t_user ORDER BY id
</select>

注意:使用了这种做法后,就需要对抽象方法名称的定义增加一个要求“不允许重载”!

3.resultMap

3.1 一对一查询中的resultMap的使用

在没有自定义别名的情况下,如果查询结果的列名与类的属性名不一致,还可以自定义<resultMap>节点进行配置,该节点的作用就是指导MyBatis封装查询到的数据!

<!-- id:自定义的名称,将应用于select节点的resultMap属性 -->
<!-- type:封装查询结果的数据类型 -->
<resultMap id="UserMap" type="cn.tedu.mybatis.User">
    <!-- result节点:将查询结果中column列对应的值封装到类的property属性中去 -->
    <result column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="password" property="password"/>
    <result column="age" property="age"/>
    <result column="phone" property="phone"/>
    <result column="email" property="email"/>
    <result column="group_id" property="groupId"/>
</resultMap>

<select id="findById" resultMap="UserMap">
    SELECT
        *
    FROM 
        t_user 
    WHERE 
        id=#{id}
</select>

在以上配置中,需要注意:<resultMap>节点中的id属性值就是<select>节点的resultMap属性值!

如果需要执行的查询操作是单表数据查询,在配置<resultMap>时,对于那些列名与属性名一致的,可以不作配置!

在配置<resultMap>时,推荐在子级使用<id>节点配置主键,然后使用<result>节点配置其它的,便于实现缓存!MyBatis有2级缓存,其中,MyBatis的1级缓存是SqlSession缓存,开发人员无法干预,2级缓存是namespace缓存,一旦开启,默认情况下,将作用于整个XML文件,需要事先在当前XML文件中添加<cache></cache>节点,表示“启用缓存”,理启用缓存,需要封装查询结果的数据类型是实现了Serializable接口的,如果某个查询不需要使用缓存,还可以在<select>节点中配置useCache="false",然后,就不需要开发人员进行其它配置了,MyBatis会自动处理缓存的数据,并且,一旦当前namespace执行了增删改类型的操作,就会重建缓存!

小结:在SQL中使用自定义别名,并在<select>中使用resultType指定封装结果的数据类型,或在SQL中使用星号表示字段列表,并配置<resultMap>节点后在<select>中使用resultMap,均可解决由于名称不一致导致无法封装查询结果的问题。

3.2 一对多查询中的resultMap的使用

在一对多的查询中,MyBatis根本就不知道怎么封装查询结果中的数据!当没有匹配的查询结果,或只有1条查询结果时,并不会报错,只是查询结果的数据不正确而已,如果查询结果有多条,则会出现如下错误信息:

Caused by: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

为了保障能够正确的封装查询结果,必须使用<resultMap>来指导MyBatis封装!并且,在SQL语句中,还需要为某个id定义别名,以保证查询结果每一列的名称都不同,否则,MyBatis只会从相同的列名中排列靠前的那一列中取数据,甚至,如果在<resultMap>中使用<id>配置主键,当出现多条数据的最靠前的那一列id值相同时,重复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="cn.tedu.mybatis.GroupMapper">

	<resultMap id="GroupVOMap" type="cn.tedu.mybatis.GroupVO">
		<id column="gid" property="id" />
		<result column="name" property="name"/>
		<!-- collection节点:用于配置1对多的属性 -->
		<!-- ofType属性:集合元素类型 -->
		<collection property="users"
			ofType="cn.tedu.mybatis.User">
			<id column="id" property="id"/>
			<result column="username" property="username"/>
			<result column="password" property="password"/>
			<result column="age" property="age"/>
			<result column="phone" property="phone"/>
			<result column="email" property="email"/>
			<result column="group_id" property="groupId"/>
		</collection>
	</resultMap>

	<select id="findVOById" resultMap="GroupVOMap">
		SELECT
			t_group.id AS gid, name,
			t_user.*
		FROM 
			t_group
		LEFT JOIN
			t_user
		ON
			t_group.id=t_user.group_id
		WHERE
			t_group.id=#{id}
	</select>

</mapper>

注意:在配置一对多的查询时,在<resultMap>中,即使存在列名与属性名完全相同的数据,也必须通过<id><result>节点进行配置!

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值