MyBatis中resultMap的相关介绍

resultMap 元素是 MyBatis 中最重要最强大的元素。它就是让你远离从结果集中取出数据的JDBC 代码的那个东西,而且在一些情形下允许你做一些JDBC不支持的事情。ResultMap 的设计就是对于一些简单的语句我们不需要明确它们的结果映射,但是到于复杂的语句确实需要描述它们的关系。

  1. 简单结果映射

    对于一个普通的JavaBean:

  2. package com.someapp.model;
    public class User {
        private int id;
        private String username;
        private String hashedPassword; 
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getUsername() {
         
            return username;
     
        }
        public void setUsername(String username) {
            this.username = username;
        }
     
        public String getHashedPassword() {
            return hashedPassword;
        }
     
        public void setHashedPassword(String hashedPassword) {
            this.hashedPassword = hashedPassword;
        }
    }
  3. 基于 JavaBean 的规范,上面这个类有 3 个属性:id,username 和 hashedPassword。这些 在 select 语句中会精确匹配到列名。 这样的一个 JavaBean 可以被映射到结果集 :
  4. <select id=”selectUsers” parameterType=”int” resultType=”com.someapp.model.User”>
        select id, username, hashedPassword
        from some_table
        where id = #{id}
    </select>
  5. 这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,基于属性名来映射列到JavaBean 的属性上。如果列名没有精确匹配,你可以在列名上使用 select 字句的别名(一个基本的SQL特性)来匹配标签。比如:
  6. <select id=”selectUsers” parameterType=”int” resultType=”com.someapp.model.User”>
        select 
        user_id as id, 
        user_name as username, 
        hashed_Password as hashedPassword
        from some_table
        where id = #{id}
    </select>
  7. 还可以通过下面的这种方式来解决列名和属性名不一致的情况:
  8. <resultMap id="userResultMap" type="User">
        <id property="id" column="user_id" />
        <result property="username" column="user_name"/>
        <result property="hashedPassword" column="hashed_password"/>
    </resultMap>
    引用它的语句使用 resultMap 属性就行了(注意我们去掉了resultType 属性,这两个属性只能包含其中的一个)
    <select id=”selectUsers” parameterType=”int” resultMap=”userResultMap”>
        select id, username, hashedPassword
        from some_table
        where id = #{id}
    </select>
  9. 2.高级结果映射

    对于下面的这个语句子我们如何进行映射呢?


    <!-- Very Complex Statement -->

    <select id="selectBlogDetails" parameterType="int" resultMap="detail edBl ogRes ultMa p">

    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,

    P.id as post_id,

    P.blog_id as post_blog_id,

    P.author_id as post_author_id,

    P.created_on as post_created_on,

    P.section as post_section,

    P.subject as post_subject,

    P.draft as draft,

    P.body as post_body,

    C.id as comment_id,

    C.post_id as comment_post_id,

    C.name as comment_name,

    C.comment as comment_text,

    T.id as tag_id,

    T.name as tag_name

    from Blog B

    left outer join Author A on B.author_id = A.id

    left outer join Post P on B.id = P.blog_id

    left outer join Comment C on P.id = C.post_id

    left outer join Post_Tag PT on PT.post_id = P.id

    left outer join Tag T on PT.tag_id = T.id

    where B.id = #{id}

    </select>

    将它映射到一个对象模型,其中包含一个作者写的博客,有很多的博文,每篇博文有零条或多条的评论和标签。下面是一个完整的复杂结果映射例子(假设作者,博客, 博文,评论和标签都是类型的别名)


    <!-- Very Complex Result Map -->

    <resultMap id="detailedBlogResultMap" type="Blog">

    <constructor >

    <idArg column="blog_id" javaType="int"/>

    </constructor>

    <result property="title" column="blog_title"/>

    <association property="author" column="blog_author_id" 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>

    <collection property="posts" ofType="Post">

    <id property="id" column="post_id"/>

    <result property="subject" column="post_subject"/>

    <association property="author" column="post_author_id" javaType="Author" />

    <collection property="comments" column="post_id" ofType=" Comment">

    <id property="id" column="comment_id"/>

    </collection >

    <collection property="tags" column="post_id" ofType=" Tag" >

    <id property="id" column="tag_id"/>

    </collection >

    <discriminator javaType="int" column="draft">

    <case value="1" resultType="DraftPost"/>

    </discriminator>

    </collection >

    </resultMap>

    resultMap 元素有很多子元素和一个值得讨论的结构。下面是 resultMap 元素的概念视图 resultMap

    • ?  constructor – 类在实例化时,用来注入结果到构造方法中
                idArg – ID 参数;标记结果作为 ID 可以帮助提高整体效能 
                arg – 注入到构造方法的一个普通结果
    • ?  id– 一个ID结果;标记结果作为ID可以帮助提高整体效能
    • ?  result – 注入到字段或 JavaBean 属性的普通结果
    • ?  association – 一个复杂的类型关联;许多结果将包成这种类型
            ? 嵌入结果映射 – 结果映射自身的关联,或者参考一个
    • ?  collection – 复杂类型的集
           ? 嵌入结果映射 – 结果映射自身的集,或者参考一个
    • ?  discriminator – 使用结果值来决定使用哪个结果映射
         ? case – 基于某些值的结果映射
          ? 嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

    2.1 id,result 

    id 和 result 都映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的单独属性或字段。这两者之间的唯一不同是 id 表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射)。 每个都有一些属性:


    属性


    描述


    property


    映射到列结果的字段或属性。如果匹配的是存在的, 和给定名称相同的JavaBeans 的属性,那么就会使用。否则 MyBatis 将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一些东西:“username”,或者映射到一些复杂的东西: “address.street.number”。


    column


    从数据库中得到的列名 ,或者是列名的重命名标签。 这也是通常和会传递给 resultSet.getString(columnName)方法参数中相同的字符串。


    javaType


    一个 Java 类的完全限定名,或一个类型别名(参加上面内建类型别名 的列表)。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。 然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的行为。


    jdbcType


    在这个表格之后的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅 仅需要对插入,更新和删除操作可能为空的列进行处理。这是 JDBC 的需要,而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定 这个类型-但仅仅对可能为空的值。


    typeHandler


    使用这个属性 ,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者 是一个类型处理器的实现,或者是类型别名。

    2.2构造方法

    <constructor >
          <idArg column="id" javaType="int"/>

    <arg column=”username” javaType=”String”/>

    </constructor>

    看看下面这个构造方法:

    public class User { //...

    public User(int id, String username) { //...

    }

    //... }

    为了向这个构造方法中注入结果,MyBatis 需要通过它的参数的类型来标识构造方法。 Java 没有自查(反射)参数名的方法。所以当创建一个构造方法元素时,保证参数是按顺序 排列的,而且数据类型也是确定的。

    <constructor >
        <idArg column="id" javaType="int"/>
        <arg column=”username” javaType=”String”/>

    </constructor>

    剩余的属性和规则和固定的 id 和 result 元素是相同的。

     2.3 关联

    <association property="author" column="blog_author_id" javaType=" Author">

    <id property="id" column="author_id"/>
         <result property="username" column="author_username"/>

    </association>

    关联元素处理“有一个”类型的关系。比如,在我们的示例中,一个博客有一个用户。 关联映射就工作于这种结果之上。你指定了目标属性,来获取值的列,属性的 java 类型(很 多情况下 MyBatis 可以自己算出来),如果需要的话还有 jdbc 类型,如果你想覆盖或获取的结果值还需要类型控制器。

    关联中不同的是你需要告诉 MyBatis 如何加载关联。MyBatis 在这方面会有两种不同的 方式:

    ? 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。
    ? 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。

    首先,让我们来查看这个元素的属性。它和普通的只由 select 和resultMap 属性的结果映射不同。


    property


    映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的 JavaBeans 的属性,那么就会使用。否则 MyBatis 将会寻找给定名称的字段。 这两种情形你可以使用通常点式的复 杂属性导航。比如,你可以 这样映射 一 些 东 西 :“ username ”, 或 者 映 射 到 一 些 复 杂 的 东 西 : “address.street.number”。


    column


    来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字符串是相同的。 注意:要处理复合主键,你可以指定多个列名通过 column=” {prop1=col1,prop2=col2}”这种语法来传递给嵌套查询语句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。


    javaType


    一个 Java 类的完全限定名,或一个类型别名(参加上面内建类型别名的列 表)。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。然而,如 果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的 行为。


    jdbcType


    在这个表格之前的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅仅 需要对插入,更新和删除操作可能为空的列进行处理。这是 JDBC 的需要, 而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定这个类型-但 仅仅对可能为空的值。


    typeHandler


    我们在前面讨论过默认的类型处理器 。使用这个属性,你可以覆 盖默认的 类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现, 或者是类型别名。

    关联的嵌套查询


    select


    另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面 有一个详细的示例。 注意:要处理复合主键,你可以指定多个列名通过 column=” {prop1=col1,prop2=col2}”这种语法来传递给嵌套查询语句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。

    示例:


    <resultMap id=”blogResult” type=”Blog”>

    <association property="author" column="blog_author_id" javaType="Author" select=”selectAuthor”/>

    </resultMap>

    <select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>

    SELECT * FROM BLOG WHERE ID = #{id}

    </select>

    <select id=”selectAuthor” parameterType=”int” resultType="Author">

    SELECT * FROM AUTHOR WHERE ID = #{id}

    </select>

    我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描述了“selectAuthor”语句应该被用来加载它的 author 属性。其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

    这种方式很简单,但是对于大型数据集合和列表将不会表现很好。问题就是我们熟知的 “N+1 查询问题”。

    所以还有另外一种方法。

    关联的嵌套结果


    resultMap


    这是结果映射的ID,可以映射关联的嵌套结果到一个合适的对象图中。这是一种替代方法来调用另外一个查询语句。这允许你联合多个表 来合成到一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis 让你“链接”结果映射,来处理嵌套结果。

    在上面你已经看到了一个非常复杂的嵌套关联的示例。下面这个是一个非常简单的示例 来说明它如何工作。代替了执行一个分离的语句,我们联合博客表和作者表在一起,就像:


    <select id="selectBlog" parameterType="int" 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=”blog_id” column="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>

    在嵌套据诶过映射中 id 元素扮演了非常重要的角色。应应该通常指定一个 或多个属性,它们可以用来唯一标识结果。实际上就是如果你离开她了,但是有一个严重的 性能问题时 MyBatis 仍然可以工作。选择的属性越少越好,它们可以唯一地标识结果。主键就是一个显而易见的选择(尽管是联合主键)。

    现在,上面的示例用了外部的结果映射元素来映射关联。这使得 Author 结果映射可以 重用。然而,如果你不需要重用它的话,或者你仅仅引用你所有的结果映射合到一个单独描 述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:


    <resultMap id="blogResult" type="Blog">

    <id property=”blog_id” column="id" />

    <result property="title" column="blog_title"/>

    <association property="author" column="blog_author_id" 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"/>

    </association>

    </resultMap>

    2.4集合

    <collection property="posts" ofType="domain.blog.Post">

    <id property="id" column="post_id"/>
        <result property="subject" column="post_subject"/>

    <result property="body" column="post_body"/>

    </collection >

    集合元素的作用几乎和关联是相同的。我们来继续上面的示例,一个博客只有一个作者。但是博客有很多文章。在博客类中, 这可以由下面这样的写法来表示:

    private List<Post> posts;

    要映射嵌套结果集合到 List 中,我们使用集合元素。就像关联元素一样,我们可以从 连接中使用嵌套查询,或者嵌套结果。

    集合的嵌套查询

    首先,让我们看看使用嵌套查询来为博客加载文章。


    <resultMap id=”blogResult” type=”Blog”>

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

    </resultMap>

    <select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>

    SELECT * FROM BLOG WHERE ID = #{id}

    </select>

    <select id=”selectPostsForBlog” parameterType=”int” resultType="Author">

    SELECT * FROM POST WHERE BLOG_ID = #{id}

    </select>

    这里你应该注意很多东西,但大部分代码和上面的关联元素是非常相似的。首先,你应 该注意我们 使用的是 集合元素 。然后要 注意那个 新的“of Ty pe ”属性。这 个属性用 来区分 JavaBean(或字段)属性类型和集合包含的类型来说是很重要的。所以你可以读出下面这个 映射:

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

    读作:“在 Post 类型的 ArrayList 中的 posts 的集合。”

    javaType 属性是不需要的,因为 MyBatis 在很多情况下会为你算出来。所以你可以缩短 写法:

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

    集合的嵌套结果

    至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType ”属性

    <select id="selectBlog" parameterType="int" 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>

    同样,如果你引用更长的形式允许你的结果映射的更多重用,你可以使用下面这个替代的映射:


    <resultMap id="blogResult" type="Blog">

    <id property=”id” column="blog_id" />

    <result property="title" column="blog_title"/>

    <collection property="posts" ofType="Post" resultMap=”blogPostResult”/>

    </resultMap>

    <resultMap id="blogPostResult" type="Post">

    <id property="id" column="post_id"/>

    <result property="subject" column="post_subject"/>

    <result property="body" column="post_body"/>

    </resultMap>

时间: 2024-11-03 21:07:46

MyBatis中resultMap的相关介绍的相关文章

在mybatis中resultMap与resultType的区别

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMapresultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用但是resultType跟resultMap不能同时存在.在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值.当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resultT

MyBatis中SQL语句相关内容

MyBatis模糊查询 使用 ${...} 代替 #{...} SELECT * FROM tableName WHERE name LIKE '%${text}%'; 在MyBatis中写SQL语句时不等于用 <> 代替 <> 多个条件中的模糊查询 SELECT * FROM 表名 WHERE (字段1 <> "" 字段2 <> "") and (字段3 LIKE '%参数%' OR 字段4 LIKE '%参数%')

mybatis中resultMap与resultType的使用说明

一.mapper文件内容如下: <mapper namespace="com.miapsoft.dao.UserDao"> <resultMap type="User" id="UserMapper"> <result property="id" column="ID" /> <result property="name" column=&quo

Mybatis中&lt;resultMap&gt;用法(主要用于一对多去重)

一.创建部门表和员工表: 创建部门信息表`t_department`,其中包括`id`, `name` CREATE TABLE t_department (         id INT AUTO_INCREMENT,         name VARCHAR(20) UNIQUE NOT NULL,         PRIMARY KEY(id)     ) DEFAULT CHARSET=UTF8; 往部门表中插入数据: INSERT INTO t_department (name) VA

Mybatis中的resultType和resultMap

一.概述 MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在. 在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值. ①当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给r

SpringBoot+MyBatis中自动根据@Table注解和@Column注解生成ResultMap

其实我一点都不想用mybatis,好多地方得自己写,比如这里. 使用mybatis要写大量的xml,烦的一批.最烦人的莫过于写各种resultmap,就是数据库字段和实体属性做映射.我认为这里应该是mybatis自动支持的,但是,它没有.为了轻量化(caocaocoa)???. 很少用mybatis,不知道有没有相关插件.只有自己写方法实现了. 先整理一下大体思路: 1.扫描项目代码下的所有类 2.选出所有类中的含有Table注解的类 3.根据column注解找出类下的属性映射关系 4.创建my

大神带你重新认识Mybatis中强大的resultMap

前言在Mybatis中,有一个强大的功能元素resultMap.当我们希望将JDBC ResultSets中的数据,转化为合理的Java对象时,你就能感受到它的非凡之处.正如其官方所述的那样: resultMap元素是 MyBatis 中最重要最强大的元素.它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作.实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap 能够代替实现同等功能的长达

Mybatis中实体类属性与数据库列表间映射方法介绍

           这篇文章主要介绍了Mybatis中实体类属性与数据列表间映射方法介绍,一共四种方法方法,供大家参考.         Mybatis不像Hibernate中那么自动化,通过@Column注解或者直接使用实体类的属性名作为数据列名,而是需要自己指定实体类属性和数据表中列名之间的映射关系,这一点让用惯了Hibernate的人很不习惯,所幸经过探索找到了建立映射关系的几种办法,其中总也有比较简单的. 首先定义一个实体类User,如下: public class User { pr

Mybatis中的resultType和resultMap 区别

Mybatis中的resultType和resultMap 是mybatis 中返回类型一定用到的,但不会同时出现.mybatis返回类型肯定是map结构,然后根据返回类型是map还是对象类型,再转换. 在给对象设置属性的时候,两个方法肯定会调用. private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException { final ResultLoaderMap lazyLoader