MyBatis配置文件(二):Mapper映射文件详解
Mapper顾名思义就是“映射”的意思,Mapper文件就是MyBatis中SQL语句的配置文件,其会在运行时加载SQL语句并映射相应参数。在MyBatis的全局配置文件SqlMapConfig.xml(mybatis-config.xml),其中就有mapper文件的资源路径的配置,因为创建SqlSessionFactory时会加载全局配置文件SqlMapConfig.xml,这说明Mapper映射文件在会话创建开始就被加载了,所以在整个工程的运行期间,Mapper映射文件有着举足轻重的作用。
1、映射文件总体介绍
Mapper映射文件,主要就是用来配置SQL映射语句的,根据不同的SQL语句性质,要使用不同的标签来包裹。
Mapper配置文件标签:
标签名称 | 标签作用 |
---|---|
insert | 用来映射插入语句。 |
update | 用来映射更新语句。 |
delete | 用来映射删除语句。 |
select | 用来映射查询语句。 |
resultMap | 用来将从数据库结果集取出的数据映射到相应的实体对象的相应字段中。 |
sql | 配置可以被其他语句引用的SQL语句块。 |
cache | 对给定命名空间的缓存配置。 |
cache-ref | 对其他命名空间缓存配置的引用。 |
parameterMap | 参数映射,该配置现已被废弃。 |
【示例】创建名为UserMapper.xml的SQL映射配置文件,实现用户信息的查询、新增、修改、删除操作的SQL语句配置。
<?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="test">
<!-- 用户信息ResultMap -->
<resultMap id="userResultMap" type="com.pjb.mybatis.po.User">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="blog_url" property="blogUrl"/>
<result column="remark" property="remark"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 根据用户编号,查询单个用户实体 -->
<select id="queryfindUserById" parameterType="int" resultMap="userResultMap">
SELECT * FROM tb_user WHERE id = #{id}
</select>
<!-- 根据用户名称,模糊查询用户列表 -->
<select id="findUserByUserName" parameterType="java.lang.String" resultType="com.pjb.mybatis.po.User">
SELECT * FROM tb_user WHERE user_name LIKE '%${value}%'
</select>
<!-- 新增用户 -->
<insert id="insertUser" parameterType="com.pjb.mybatis.po.User">
INSERT INTO tb_user(user_name,blog_url,remark,create_time)
VALUES(#{userName},#{blogUrl},#{remark},
#{createTime,typeHandler=com.pjb.mybatis.handler.DateStrTypeHandler});
</insert>
<!-- 修改用户 -->
<update id="updateUser" parameterType="com.pjb.mybatis.po.User">
UPDATE tb_user SET user_name = #{userName} ,blog_url=#{blogUrl} ,remark=#{remark} WHERE id = #{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
DELETE FROM tb_user WHERE id = #{id}
</delete>
</mapper>
在以上示例语句中,parameterType为输入参数类型,parameterType为输出参数类型。SQL语句中的“#{}”是占位符,其如同JDBC的预编译SQL中的“?”,只是在该配置中会将“#{}”中的内容自动传递到预处理语句中。
在insert、update、delete及select配置标签中可以配置很多属性,具体可以配置的属性如下:
<select
id="selectPerson"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
各属性的含义:
属性名 | 含义 |
---|---|
id | SQL映射配置的唯一标识,可以代表SQL配置。 |
parameterType | 可选属性,用来传入SQL配置中需要的参数类型的类名或别名。 |
resultType | 从这条语句中返回的期望类型的类的完全限定名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用。 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂映射的情形都能迎刃而解。可以使用 resultMap 或 resultType,但不能同时使用。 |
flushCache | 设置语句调用时,是否清空本地缓存和二级缓存,默认为false。 |
useCache | 设置语句调用时,执行结果是否保存二级缓存,对select元素默认为false。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动)。 |
fetchSize | 设置驱动程序每次批量返回结果的行数。 |
statementType | 设置MyBatis的statement类型。可以配置为STATEMENT,PREPARED 或 CALLABLE 中的一个,表示使用Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | 设置MyBatis的结果集类型。可以配置为FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖驱动)。 |
databaseId | 在配置databaseIdProvider(数据库厂商标识)的情况下,MyBatis会加载所有不带databaseId或者匹配当前databaseId的语句。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。 这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 |
resultSets | 当有多个结果集的时候使用,会为SQL执行后返回的每个结果集设定一个名称,以逗号分隔。 |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。 |
2、Mapper配置输入映射
在增、删、改、查配置标签中,有许多SQL配置是需要传递参数的。在MyBatis的SQL映射配置文件Mapper.xml中,输入参数属性配置在parameterType中。对于parameterType属性,可以配置的基本数据类型有:int、double、float、short、long、byte、char、boolean,基本数据包装类有:Byte、Short、Integer、Long、Float、Double、Boolean、Character,还有Java复杂数据类型JavaBean或其他自定义的封装类。
【示例】使用parameterType属性映射基本数据类型、基本数据包装类及自定义包装类(如:JavaBean)。
当需要为传递参数指定一个特殊的数据库类型时,可以在“#{}”中添加对该类型对应的数据库JDBC类型描述,以便MyBatis在映射时进行对应的转换:
#{number,javaType=int,jdbcType=NUMERIC}
前面提到过“typeHandlers(类型处理器)”,当该类型对应的某列为空时,需要设置处理这种类型参数的Handler,例如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=AgeTypeHandler}
对于一些需要保留精度的数值类型的参数,可以为其添加保留小数点位数的设置,可以添加numericScale属性,为该参数设置小数点后保留的位数(如:保留2位小数),如下:
#{price,javaType=double,jdbcType=DECIMAL,numericScale=2}
这句配置指定“price(价格)”参数保留小数点后两位。
MyBatis也支持使用存储过程的配置。当使用存储过程时,需要设置一个参数“mode”,其值有IN(输入参数)、OUT(输出参数)和INOUT(输入/输出参数)。MyBatis定义存储过程如下:
使用“#{}”时MyBatis会创建预处理语句属性,用于安全地设置对应的值。而当需要在SQL中插入一个不会被改变的字符串,或想要拼接SQL语句时(例如order by),可以使用“${}”的方式来进行拼接,例如可以从外部控制一个查询结果如何排序(其中orderColumn可以是id、username等User的各个列):
MyBatis在加载SQL配置语句中“${}”的字符串内容时,不会改变或转义该字符串。
注意:使用“${}”接受用户传来的字符串并将其拼接到SQL语句中是不安全的,会引发SQL注入攻击,所以在使用时,应该保证其中的内容不是由用户传递过来的。尽管这样,还是尽量不要使用“${}”在SQL上拼接字符串。
3、Mapper配置输出映射
在MyBatis的Mapper映射文件中,SQL语句查询后返回的结果,会映射到配置标签的输出映射属性对应的Java类型。Mapper的输出映射有两种配置,分别是resultType和resultMap。
3.1 resultType
resultType除了像parameter一样支持基本数据类型、基本数据包装类之外,也支持自定义包装类(如:JavaBean)。关于自定义包装类,如果从数据库查询出来的列名与包装类中的属性名全都不一致,则不会创建包装类对象,如果数据库查询出来的列名与包装类的属性名至少有一个一致,那么就会创建包装类对象。resultType使用如下:
从第二条查询方法可以看出,查询结果可能是一条或者多条数据,但是resultType都是只配置了User类,这说明,在MyBatis中,不管输出的是JavaBean单个对象还是一个列表(list中包含JavaBean),在Mapper映射文件中resultType指定的类型都是一样的。
【示例】使用resultType配置输出自定义包装类(如:JavaBean)结果。
(1)在com.pjb.mybatis.po包下,创建用户信息持久化类(User.java类)。
package com.pjb.mybatis.po;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
import java.util.Date;
/**
* 用户信息持久化类
* @author pan_junbiao
**/
public class User implements Serializable
{
private int id; //用户编号
private String userName; //用户姓名
private String blogUrl; //博客地址
private String remark; //备注
private String createTime; //创建时间
//省略getter与setter方法...
}
(2)编写方法,获取数据并遍历数据。
/**
* 根据用户编号,查询单个用户实体
* @author pan_junbiao
*/
public static void findUserById()
{
DataConnection dataConnection = new DataConnection();
SqlSession sqlSession = dataConnection.getSqlSession();
User user = sqlSession.selectOne("test.findUserById", 1);
if(user!=null)
{
System.out.println("使用resultType配置输出自定义包装类(如JavaBean)结果:");
System.out.println("用户编号:" + user.getId());
System.out.println("用户姓名:" + user.getUserName());
System.out.println("博客地址:" + user.getBlogUrl());
System.out.println("备注信息:" + user.getRemark());
System.out.println("创建时间:" + user.getCreateTime());
}
sqlSession.close();
}
执行结果:
但是在相应的Mapper方法中,加载该SQL配置时,如果输出单个对象,则方法返回值是单个JavaBean对象类型,如果输出一个列表,则方法的返回值为List
最后,如果没有合适的JavaBean接受结果集数据,resultType还可以输出HashMap类型的数据,将输出的字段名称作为map的key,value为字段值。如果是集合,那是因为list里面嵌套了HashMap。
【示例】使用resultType配置输出HashMap类型的数据。
(1)在SQL映射配置文件(UserMapper.xml)中编写select方法,配置resultType的返回结果为HashMap类型。
(2)编写方法,获取HashMap数据并遍历数据。
/**
* 根据用户编号,查询用户信息(HashMap)
* @author pan_junbiao
*/
public static void findUserHashMap()
{
DataConnection dataConnection = new DataConnection();
SqlSession sqlSession = dataConnection.getSqlSession();
HashMap userHashMap = sqlSession.selectOne("test.findUserHashMap", 1);
if(userHashMap!=null)
{
System.out.println("使用resultType配置输出HashMap类型的数据:");
System.out.println("用户编号:" + userHashMap.get("id"));
System.out.println("用户姓名:" + userHashMap.get("user_name"));
System.out.println("博客地址:" + userHashMap.get("blog_url"));
System.out.println("备注信息:" + userHashMap.get("remark"));
System.out.println("创建时间:" + userHashMap.get("create_time"));
}
sqlSession.close();
}
执行结果:
提示:一般来说,resultType所指的输出类型是一种Java的原始或包装类型,并且从数据库取出的字段名称无须任何转换。
3.2 resultMap
如果在SQL映射文件中配置的SQL语句返回的结果为多个值,且没有一个完全与返回结果值一一匹配的封装类去接受,或者此时寄希望于使用一个容器接收结果集结果数据,到业务层再按情况处理它们。为此,MyBatis提供了一种SQL结果集输出映射类型,即resultMap。可以通过定义一个resultMap在列名和Java包装类属性名之间创建映射关系。
使用resultMap可以定义一个结果集配置,该配置声明了SQL查询结果集中的每一个字段与type中指定的Java实体类的哪个属性名对应,以及该配置最终生成的类型格式。下面是一个resultMap示例:
这里对于select配置,使用resultMap进行输出映射,其中“userResultMap”就是一个resultMap配置的id,表明该SQL配置的结果集要指向那个resultMap配置。如果resultMap在其他的Mapper配置文件中,则需要在id前面加上那个Mapper配置文件的namespace。
使用id为“userResultMap”的resultMap配置将select查询语句和User类中的属性进行映射。id属性是resultMap的唯一标识,而type是最终所映射的Java对象类型,可以使用别名。在resultMap标签对中,id标签指的是查询结果集中的唯一标识(比如User的唯一标识就是id),result标签指的是普通列的定义(User类中的其他非主键属性),其column指的是SQL语句查询出的列名,然后对应的property是type所指定的Java包装类中的属性名,最终resultMap会对column和property进行映射(对应关系),这样最终就会拿到一个填充了查询结果的User类。
提示:一般来说,数据库的结果集中的列名与Java实体类中的属性的名称是不同的,所以需要resultMap来对列名进行转换才能映射至Java实体类,有时候还需要指定相应的数据类型。
还没有评论,来说两句吧...