映射配置文件
本文将详细介绍 MyBatis 的映射配置文件,以及 select、insert、update、delete、resultMap、cache 等属性的使用。
映射配置文件结构
<?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="UserMapper">
<!--查询所有-->
<select id="findAll" resultType="me.iling.User">
select * from user
</select>
<!--插入数据-->
<insert id="insertUser">
insert into user (id,username,password,email)
values (#{id},#{username},#{password},#{email})
</insert>
<!--更新数据-->
<update id="updateUser">
update user set
username = #{username},
password = #{password},
email = #{email}
where id = #{id}
</update>
<!--删除数据-->
<delete id="deleteUser">
delete from user where id = #{id}
</delete>
</mapper>
<!DOCTYPE mapper ... >
:映射文件的 DTD 约束头。<mapper namespace=...>
:mapper
:是映射文件根元素namespace
:命名空间,与<select id >
一起用于确定坐标
<select id=... resultType=...>
:select
: 元素指定 SQL 执行类型,可选的还有insert
、update
、delete
。id
:与<mapper namespace >
一起构成查询坐标。resultType
:查询结果对应的实体类型。
select 元素
select
元素支持的完整属性如下:
<select
id="findAll"
parameterType="int"
parameterMap="deprecated"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
</select>
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以根据语句中实际传入的参数计算出应该使用的类型处理器 (TypeHandler )。默认值:未设置。 |
resultType | 期望从这条语句中返回结果的类全限定名或别名。注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 |
resultMap | 对外部 resultMap 的命名引用。resultType 和 resultMap 之间只能同时使用一个。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。 |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来。默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数(依赖数据库驱动)。默认值:未设置。 |
fetchSize | 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值(依赖驱动)。默认值:未设置。 |
statementType | 可选 STATEMENT ,PREPARED 或 CALLABLE 。这会让 MyBatis 分别使用 Statement ,PreparedStatement 或 CallableStatement ,默认值:PREPARED 。 |
resultSetType | FORWARD_ONLY ,SCROLL_SENSITIVE , SCROLL_INSENSITIVE 或 DEFAULT (等价于未设置) 中的一个(依赖数据库驱动),默认值:未设置。 |
databaseId | 如果配置了数据库厂商标识 (databaseIdProvider ),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句:如果为 true,则假设结果集以正确顺序(排序后)执行映射,当返回新的主结果行时,将不再发生对以前结果行的引用。这样可以减少内存消耗。默认值:false。 |
resultSets | 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。 |
affectData | 将其设置为 true,用于编写返回数据的 INSERT、UPDATE 或 DELETE 语句,以便正确地控制事务。默认值:false (since 3.5.12)。 |
insert, update 和 delete 元素
数据变更语句 insert,update 和 delete 的属性非常接近:
<insert
id="insertUser"
parameterType="domain.blog.User"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
</insert>
<update
id="updateUser"
parameterType="domain.blog.User"
flushCache="true"
statementType="PREPARED"
timeout="20">
</update>
<delete
id="deleteUser"
parameterType="domain.blog.User"
flushCache="true"
statementType="PREPARED"
timeout="20">
</delete>
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以根据语句中实际传入的参数计算出应该使用的类型处理器 (TypeHandler ),默认值:未设置。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空。默认值:(对 insert 、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数(依赖数据库驱动)。默认值:未设置。 |
statementType | 可选 STATEMENT ,PREPARED 或 CALLABLE 。这会让 MyBatis 分别使用 Statement ,PreparedStatement 或 CallableStatement ,默认值:PREPARED 。 |
useGeneratedKeys | (仅适用于 insert 和 update )这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update )指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update )设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识 (databaseIdProvider ),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
插入数据后,立刻返回主键
很多时候,我们希望向数据库插入一条记录后,能立即拿到这条记录的主键值。对于支持自增主键的数据库,我们可以使用上文表格中介绍的 useGeneratedKeys
属性:
<insert id="save" parameterType="me.iling.pojo.User"
useGeneratedKeys="true"
keyProperty="id">
insert into user(username, birthday, sex, address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
useGeneratedKeys="true"
启用返回主键;keyProperty="id"
把返回主键的值,封装到 Bean 实体的id
属性中。
如果使用的数据库不支持自动生成主键,也可以使用 selectKey
元素获取插入元素:
<insert id="save" parameterType="me.iling.pojo.User">
<selectKey
keyColumn="id"
keyProperty="id"
resultType="int"
order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
INSERT INTO `user` (username,birthday,sex,address)
VALUES (#{username},#{birthday},#{sex},#{address})
</insert>
keyColumn="id"
指定主键列名;keyProperty="id"
指定主键封装到 Pojo 实体的属性中;resultType="int"
指定主键类型;order="AFTER"
设置在 SQL 语句执行前(后),执行此语句。
selectKey 标签适用范围更广,支持所有类型数据库。
sql 元素
sql
元素可以用来定义可重用的 SQL 代码片段,以便在其它语句中使用。 参数可以静态地(在加载的时候)确定下来,并且可以在不同的 include
元素中定义不同的参数值。比如:
<sql id="userColumns">
${alias}.id,${alias}.username,${alias}.password
</sql>
这个 SQL 片段可以在其它语句中使用,例如:
<select id="selectUsers" resultType="map">
select
<include refid="userColumns">
<property name="alias" value="t1"/>
</include>,
<include refid="userColumns">
<property name="alias" value="t2"/>
</include>
from some_table t1
cross join some_table t2
</select>
也可以在 include
元素的 refid
属性或内部语句中使用属性值,例如:
<sql id="sometable">
${prefix}Table
</sql>
<sql id="someinclude">
from
<include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>
参数传递
#{} 方式传递参数
MyBatis 默认情况下推荐使用 #{}
语法传递参数,通过这种方式传递参数时,MyBatis 会创建 PreparedStatement
参数占位符安全地设置参数。例如:
#{height,
javaType=double,
jdbcType=NUMERIC,
typeHandler=MyTypeHandler,
numericScale=2}
#{}
传递参数时可以通过多种属性进行自定义:
escape
:是否转义百分号(%)和下划线(_)。默认情况下,MyBatis 会转义这些字符,以避免 SQL 注入攻击。可以通过设置escape
属性来禁用转义。map
:指定一个Map
对象,用于将键值对传递给 SQL 语句中的参数。javaType
:指定参数的 Java 类型。MyBatis 将根据该类型自动将参数转换为相应的数据库类型。jdbcType
:指定参数的 JDBC 类型。这个属性可以用来指定特定的 JDBC 类型,以便正确地设置PreparedStatement
的参数。mode
:指定参数的处理方式。常见的模式包括:IN
、OUT
、INOUT
等。resultMap
:指定结果映射的配置。可以将参数映射到结果集中的列,从而实现对象与数据库列之间的映射。null
:指定当参数为null
时的处理方式。默认情况下,MyBatis 会将null
参数设置为 SQL 语句中的NULL
值。
尽管上面这些选项很强大,但大多时候,我们只须简单的指定属性名。
${} 字符串替换
${}
语法用于插入未经转义的字符串,当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,${}
字符串替换将会非常有用。举个例子,如果我们想 select 一个表的任意一列数据,不需要明确指定列名,而是可以使用 ${}
语法动态替换列名。这样做可以更加灵活地构建 SQL 语句,适用于更加复杂的应用场景。例如:
@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);
/* 调用
User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "ling");
User userOfEmail = userMapper.findByColumn("email", "me@mmail.io");
*/
其中 ${column}
会被直接替换,而 #{value}
会使用 ?
预处理。
resultMap 结果映射
如果实体的属性名与表中字段名不一致,可以使用 resultMap
实现手动关系映射。示例如下:
<mapper namespace="me.iling.UserMapper">
<resultMap id="userResultMap" type="user">
<id colum="uid" property="id"/>
<result column="NAME" property="username"/>
<result column="PASSWORD" property="password"/>
</resultMap>
<select id="findAllResultMap" resultMap="userResultMap">
SELECT id AS uid,username AS NAME,password AS PASSWORD FROM USER
</select>
</mapper>
resultMap
:id
元素:表示实体对象的主键。column
属性:表中主键的名称、别名;property
属性:实体对象主键的属性名。
result
元素:表示实体对象的普通属性。column
属性:表中普通字段的名称、别名;property
属性:实体对象属性名。
通过映射 column
与 property
,MyBatis 就可以为我们自动的将查询到的数据正确的封装到 Java 实体对象中。