2.7 mybatis结果集映射

2017-12-05 01:26:43 13,492 0

结果集映射指的是,将数据库表的字段映射到Java实体的属性上。mybatis支持多种结果集映射方式:

1、resultType

2、resultType+起别名

3、resultMap

4、@ResultMap注解

5、mapUnderscoreToCamelCase

1 resultType

resultType适用于数据库表字段和java实体类属性是一 一对应的,如:

user表

CREATE TABLE `user` (
   `id` int(11) NOT NULL,
   `name` varchar(255) NOT NULL,
   `age` int(11) DEFAULT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

User类

public class User {
    private int id;
    private String name;
    private int age;
    //...setters and getters
}

此时我们可以在xml文件中这样配置<select>元素

<select id="selectById" parameterType="int" resultType="com.tianshouzhi.mybatis.quickstart.domain.User">
        select id,name,age from user where id= #{id}
</select>

mybatis在查询数据库记录后,会首先尝试调用User类的属性方法进行设置值。以user表的name字段为例:

1、首先查看resultType元素指向的User类中有没有对应的setName方法,如果有,调用setName方法设置值

2、如果没有setName方法,则会尝试通过反射技术,查看User类中有没有一个字段叫做name,如果有,通过反射技术给其赋值(说明set方法不是必须的)

3、如果既没有setName方法,也没有name字段,则mybatis放弃这个字段的映射,也不会抛出异常


2、resultType+起别名

        当数据库表字段与实体属性就是不一致的,如user表中,表示的用户名的字段叫name,而在User类中,只有username字段和对应的setUsername方法。那么只给<select>元素设置resultType属性,就无法给User类的username字段赋值。此时可以通过起别名的方式:

<select id="selectById" parameterType="int" resultType="com.tianshouzhi.mybatis.quickstart.domain.User">
        select id,name as username,age from user where id= #{id}
</select>

上面使用as,给name列起了一个别名为username,通过这种方式,就可以将user表的username字段映射到User类的name字段上。

注意,这种方式依赖于<settings>元素中useColumnLabel属性为true,其作用是:使用列标签代替列名。这个配置项默认为true,如果改为false,则通过别名的方式无法映射,读者可以自行尝试。

<configuration>
   <!--使用列标签代替列名,取值true | false,默认为true,改为false的无法通过别名映射。-->
    <settings>
        <setting name="useColumnLabel" value="true"/>
    </settings>
    <!--其他配置-->
</configuration>

3、resultMap

        如果数据库表多个字段与实体类中的字段或属性名称都不相同,那么通过起别名的方式,就显得太麻烦了,因为我们在一个映射文件中可能需要写多个<select>元素,每个里面都要其别名,极容易出错。

        此时我们可以在mappers配置文件中配置一个<resultMap>元素,如下

<?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="com.tianshouzhi.mybatis.quickstart.mapper.UserMapper">
    <!--定义resultMap元素-->
    <resultMap id="userMap" type="com.tianshouzhi.mybatis.resultmap.User">
        <id column="id" property="id"  javaType="java.lang.Integer" jdbcType="INTEGER"/>
        <result column="name" property="username"  javaType="java.lang.String" jdbcType="VARCHAR"/>
        <result column="age" property="age" javaType="java.lang.Integer" jdbcType="INTEGER"/>
    </resultMap>

 <!--使用resultMap属性代替resultType,其值为上面<resultType>元素的id属性值-->
    <select id="testResultMap" parameterType="int" resultMap="userMap">
        select id,name,age from user where id= #{id}
    </select>
</mapper>

在上面的代码中,我们配置了一个<resultMap>元素,然后在<select>元素中,通过resultMap属性指向<resultMap>元素的id字段的值。

注意这里经常会有人忘记将resultType改成resultMap,如:

<!--错误的用法:直接将resultType值改为userMap,resultType的属性值应该是java类全路径或者别名-->
<select id="testResultMap" parameterType="int" resultType="userMap">
        select id,name,age from user where id= #{id}
    </select>

如果这样写了,mybatis会抛出异常,因为resultType的属性值应该是java类全路径或者别名(alias).

关于resultMap元素的解释:

     id属性用于表示这个<resultMap>唯一标识(说明我们可以在一个映射文件中配置多个<resultMap>元素),type属性表示这个<resultMap>元素配置的是哪一个Java类的映射关系。

    上面的<resultMap>中,内部还配置了<id>子元素和<result>子元素,分别表示:数据库表主键与Java类属性的映射关系、数据库表其他字段与Java类属性的映射关系。这两个元素都包含以下属性:

    • column:数据库表字段名称

    • property:java类的属性名称

    • javaType:java类属性的类型

    •  jdbcType :数据库字段对应的Jdbc type类型     

    对于javaType属性和jdbcType属性暂时可以不配置,mybatis会自动进行检测,在后面的章节,笔者会列出所有jdbcType和javaType的对应关系。

    特别的,在我们这个案例中,只有数据库表name字段和User类的username属性没有对应上,而id和age都是完全对应的。事实上,我们可以在<resultMap>元素中只配置usename和name的映射关系。不过一般情况下,都会进行完整的配置,否则看起来会有点怪异。

    回到主题,我们只是想配置一下数据库表字段和java类属性的映射关系,通过<resultMap>元素 配置,好像变得太复杂了。配置映射关系只是<resultMap>元素的基本功能,其内部还可以配置<association>、<collection>子元素,用于建立数据表的关联关系(一对一,一对多,多对多),这才是<resultMap>的核心威力,关于关联关系映射,我们将在下一节讲解。

4、@ResultMap注解  

    在mybatis快速入门中,我们提到了mybatis的映射关系除了xml映射文件,还可以通过注解来配置。而@ResultMap无非就是注解版的<resultMap>元素。这里暂时不做介绍,后面有一节专门介绍mybatis的所有的注解是如何使用的。


5、终极大杀器:mapUnderscoreToCamelCase

    mapUnderscoreToCamelCase的意思是,将下划线(underscore)"_"规则的命名风格转换为驼峰(camel)命名风格。

    在使用mysql时,如果表字段由多个单词组成,我们通常使用下划线"_"来分割多个单词,例如记录一个用户的注册时间(register time),通常会命名为register_time,

    而在java代码中,我们通常使用驼峰命名规则,因此会名为registerTime。

    对于这种典型的转换,mybatis提供了mapUnderscoreToCamelCase配置项,这是一个开关选项,取值true|false,默认为false。当我们设置为true时,mybatis就会自动帮我们进行转换。

     配置方式如下:

     在mybatis全局配置文件mybatis-config.xml中,新增以下配置

<configuration>
   <!--开启下划线"_"与驼峰命名规则自动转换-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--其他配置-->
</configuration>

此时,对于这样的sql

<select id="selectById" parameterType="int" resultType="com.tianshouzhi.mybatis.quickstart.domain.User">
        select id,name,register_time from user where id= #{id}
</select>

我们可以通过resultType直接指定实体类,不需要通过resultMap元素进行繁琐的配置。