2.7 mybatis结果集映射
结果集映射指的是,将数据库表的字段映射到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元素进行繁琐的配置。