Mybatis的xml(mapper)映射用法

一、结果映射(resultMap)

resultMap 元素有很多子元素:

  • constructor - 用于在实例化类时,注入结果到构造方法中
    • idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
    • arg - 将被注入到构造方法的一个普通结果
  • id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
  • result – 注入到字段或 JavaBean 属性的普通结果
  • association – 一个复杂类型的关联;许多结果将包装成这种类型
    • 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
  • collection – 一个复杂类型的集合
    • 嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用
  • discriminator – 使用结果值来决定使用哪个 resultMap
    • case – 基于某些值的结果映射
      • 嵌套结果映射 – case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射

1.1 id & result结果映射元素

idresult是一个结果映射的最基础元素

<resultMap id="resultMapOne" type="Demo">
	<id property="id" column="post_id"/>
	<result property="subject" column="post_subject"/>
</resultMap>
  1. idresult元素都是将一个列的值映射到一个简单数据类型(String, int, double, Date 等等)的属性或字段。
  2. 这两者之间的唯一不同是,id元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

IdResult元素的属性:

属性描述
property指定列结果映射的字段或属性。如果 JavaBean 有这个名字的属性如username,就会把查询到的值映射到username。还可以使用点式分隔形式进行复杂映射, 如映射到animal属性的name属性:animal.name
column表列名或列的别名。一般情况下,和用getter方法给字段赋值一样。
javaType一个Java类的全限定名,映射到一个JavaBean,MyBatis通常可以推断类型。然而,如果你映射到的是HashMap,应该明确地指定javaType来保证行为与期望的相一致。
jdbcTypeJDBC 类型,只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。
typeHandler使用这个属性,可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的全限定名,或者是类型别名。

1.2 constructor构造器元素

有些情况下想使用不可变类,只在构造方法初始化时才能为类属性赋值,constructor 元素就是为此而生的。

public class User {
   //...
   public User(Integer id, String username, int age) {
     //...
  }
}

为了将结果注入构造方法,MyBatis 需要通过某种方式定位相应的构造方法,从版本 3.4.3 开始,可以在指定参数名称的前提下,以任意顺序编写 arg 元素。

<resultMap id="resultMapTwo" type="User">
	<constructor>
   		<idArg column="id" javaType="int" name="id" />
   		<arg column="age" javaType="_int" name="age" />
   		<arg column="username" javaType="String" name="username" />
	</constructor>
</resultMap>

1.3 association关联元素

association元素用来处理关联嵌套关系, 比如一个博客有一个用户。关联结果映射和其它类型的映射工作方式差不多。需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来)

属性描述
property指定列结果映射的字段或属性。如果 JavaBean 有这个名字的属性如username,就会把查询到的值映射到username。还可以使用点式分隔形式进行复杂映射, 如映射到animal属性的name属性:animal.name
javaType一个Java类的全限定名,映射到一个JavaBean,MyBatis通常可以推断类型。然而,如果你映射到的是HashMap,应该明确地指定javaType来保证行为与期望的相一致。
jdbcTypeJDBC 类型,只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。
typeHandler使用这个属性,可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的全限定名
column表列名或列的别名。一般情况下,和用getter方法给字段赋值一样。 注意:在使用复合主键的时候,可以使用 column="{prop1=col1,prop2=col2}" 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
select子查询(嵌套查询)语句的 ID,它会把column属性指定的列的检索数据,作为参数传递给目标select语句。
fetchType可选的。有效值为 lazy 和 eager。 指定属性后,将在映射中忽略全局配置参数 lazyLoadingEnabled,使用属性的值。
resultMap结果映射的 ID,可以将此关联的嵌套结果集映射到一个合适的对象树中。 它可以作为使用额外 select 语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。

1.3.1 嵌套结果映射

把查询出来的关联结果映射到属性的属性中,如下把作者相关的关联数据author_idauthor_username映射到Author属性的相关属性idusername中。

  1. 直接在< association >元素内指定映射关系。
<association property="author" column="blog_author_id" javaType="Author">
	<id property="id" column="author_id"/>
	<result property="username" column="author_username"/>
</association>
  1. 通过resultMap属性指定一个结果集
<select id="selectBlog" resultMap="blogResult">
 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
 from Blog B left outer join Author A on B.author_id = A.id
 where B.id = #{id}
</select>

<resultMap id="blogResult" type="Blog">
 <id property="id" column="blog_id" />
 <result property="title" column="blog_title"/>
 <association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/>
</resultMap>

<resultMap id="authorResult" type="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"/>
</resultMap>

1.3.2 嵌套子查询

在结果映射中嵌套一个子查询,用column属性指定一个或多个列字段作为参数,如author_id,传递给用select属性指定的id = selectAuthor的查询语句去执行子查询并封装到javaType属性指定的属性中。

<resultMap id="blogResult" type="Blog">
	<id property="id" column="blog_id"/>
	<result property="context" column="context"/>
	<association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
	SELECT blog_id,context,author_id FROM BLOG WHERE blog_id = #{id}
</select>

<select id="selectAuthor" resultType="Author">
	SELECT * FROM AUTHOR WHERE author_id = #{id}
</select>

1.3.3 嵌套多结果映射

这个关于resultSet属性,暂时没用到,先不了解。

1.4 collection 集合元素

集合元素和关联元素几乎是一样的,相似的程度很高,直接上案例!

一个博客Blog只有一个作者Author,但一个博客有很多文章Post。 在博客类中,这可以用下面的写法来表示:

private List<Post> posts;

要像上面这样,映射嵌套结果集合到一个List中,可以使用集合元素。 和关联元素一样。可以使用嵌套Select查询,或基于连接的嵌套结果映射集合。

1.4.1 嵌套子查询

<resultMap id="blogResult" type="Blog">
  <collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap>

<select id="selectBlog" resultMap="blogResult">
  SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id="selectPostsForBlog" resultType="Post">
  SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

仔细观察会注意到与关联元素对比,这个集合元素多了一个新的ofType属性。这个属性非常重要,它用来将JavaBean属性的类型和集合存储的类型区分开来。

所以语句:

<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>

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

<collection property="posts" column="id" ofType="Post" select="selectPostsForBlog"/>

用法与关联元素相似

<select id="selectBlog" resultMap="blogResult">
  select
  B.id as blog_id,
  B.title as blog_title,
  B.author_id as blog_author_id,
  P.id as post_id,
  P.subject as post_subject,
  P.body as post_body,
  from Blog B
  left outer join Post P on B.id = P.blog_id
  where B.id = #{id}
</select>

<resultMap id="blogResult" type="Blog">
  <id property="id" column="blog_id" />
  <result property="title" column="blog_title"/>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <result property="body" column="post_body"/>
  </collection>
</resultMap>

参考官方文档

二、其他例子

1 结果对象中包含类似 List< String > 这样的集合

模型

public class DesktopGroup {
	private Long id;
   	private String name;
    @TableField(exist = false)
    private List<String> vmIds;
}

mapper

<resultMap id="baseMapWithVmids" type="com.wipinfo.central.engine.entity.DesktopGroup">
	<id column="id" property="id" jdbcType="VARCHAR"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <!-- 
    	集合填充对象 property="vmIds"  
    	数据类型 ofType="java.lang.String"
   	-->
   	<collection property="vmIds" ofType="java.lang.String">
   		<!-- 查询列 column="desk_id" ,因为是 String 类型,所以没有 property 属性 -->
    	<result column="desk_id"/> 
	</collection>
</resultMap>

<select id="selectListWithVmIds" resultMap="baseMapWithVmids">
	select id,name,desk_id
	FROM aaa_jdbc.t_wipinfo_engine_desktopgroups d
	INNER JOIN aaa_jdbc.t_wipinfo_engine_desk_group dg
	ON d."id" = dg.group_id
</select>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值