Mybatis中的resultType和resultMap

发布时间 2023-08-15 15:02:13作者: NorthnightX

综述

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接返回设置的类型,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。

  1. 当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
  2. 当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用

ResultType

resultType 用于指定查询结果的目标类型,通常是一个简单的数据类型(如整数、字符串等)或者一个JavaBean。这种方式适用于查询返回单个基本数据类型或者一个简单的Java对象,不需要额外的映射配置。

返回一个实体类对象

<select id="queryByBlogger" resultType="com.ntx.common.domain.TBlogType">
    select * from t_blog_type
    <where>
        blogger = #{blogger}
    </where>
</select>

返回一个List

<select id="getPage" resultType="com.ntx.blog.domain.TBlog">
    select * from t_blog
    <where>
    <if test="tBlog.title != null">
        and title like #{tBlog.title}
    </if>
    <if test="tBlog.typeId != null">
        and type_id = #{tBlog.typeId}
    </if>
    </where>
    limit #{start}, #{pageSize}
</select>

返回一个字符串

<select id="getUserNameById" resultType="java.lang.String">
	SELECT name FROM users WHERE id = #{id}
</select>

返回一个Map

<select id="getUserById" resultType="java.util.Map">
	SELECT id, name, age FROM users WHERE id = #{id}
</select>

ResultMap

虽然resultType 属性在大部分情况下都够用,但是在一些特殊情况下无能为力,比如属性名和列名不一致,为一些连接的复杂语句编写映射代码

定义Map映射

id和result
id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

<resultMap id="brandResultMap"(唯一标识) type="pojo.Brand"(映射的类型,支持别名)>
	<!-- column:库表的字段名 property:实体类里的属性名 -->
	<id(完成主键字段的映射 ) column="company_No" property="companyNo" />
	<result(完成一般字段的映射) column="brand_name"(表的列名)property="brandName(实体类的属性名)" />
</resultMap>

执行SQL

<select id="selectAll" resultMap="brandResultMap">
	select * from tb_brand;
</select>

一对一映射

<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
	select
		B.id as blog_id,
		B.title as blog_title,
		B.author_id as blog_author_id,
		A.id as author_id,
		A.username as author_username,
		A.password as author_password,
		A.email as author_email,
		A.bio as author_bio,
		A.favourite_section as author_favourite_section
	from Blog B
		left outer join Author A on B.author_id = A.id
	where B.id = #{id}
</select>

一对一的关联关系情况,我们通过association配置就可以解决这个问题:

<resultMap id="detailedBlogResultMap" type="Blog">
	<constructor>
		<idArg column="blog_id" javaType="int"/>
	</constructor>
	<result property="title" column="blog_title"/>
	<association property="author" javaType="Author">
		<id property="id" column="author_id"/>
		<result property="username" column="author_username"/>
		<result property="password" column="author_password"/>
		<result property="email" column="author_email"/>
		<result property="bio" column="author_bio"/>
		<result property="favouriteSection" column="author_favourite_section"/>
	</association>
</resultMap>

映射在 javaBean 中的表示:

private Author author;

一对多映射

<resultMap id="userMap" type="User">
	<id property="id" column="id"/>
	<result property="name" column="name"/>
	<collection property="orders" ofType="Order">
   		<id property="orderId" column="order_id"/>
    		<result property="orderName" column="order_name"/>
    		<result property="orderDate" column="order_date"/>
	</collection>
</resultMap>

<select id="getUserWithOrders" resultMap="userMap">
	SELECT u.id, u.name, o.order_id, o.order_name, o.order_date
	FROM users u
	LEFT JOIN orders o ON u.id = o.user_id
	WHERE u.id = #{id}
</select>

javaBean 中我们这样表示集合:

private List<Order> orders;

大部分都上面的association非常相似,这里只是新增了一个 ofType属性。
这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。 所以你可以按照下面这样来阅读映射:

<collection property="orders" javaType="ArrayList" ofType="Order"/>

读作:“orders 是一个存储 Order 的 ArrayList 集合”。
一般情况下,MyBatis 可以推断 javaType 属性,因此并不需要填写。所以很多时候可以简略成:

<collection property="orders" ofType="Order"/>