MyBatis映射器详解
半塘 1/11/2023 MyBatis框架
在CRUD【增删改查】章节中,我们已经了解了MyBatis的基本使用,对于MyBatis来说,映射功能是其核心功能。本章对映射器的使用进行详细介绍。
# 1、select
# 1.1、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">
SELECT * FROM user WHERE id = #{id}
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
id="selectPerson
": Mapper方法名称,对应selectPerson方法parameterType="int
":参数类型为intparameterMap="deprecated
":参数映射已过时,可能不再使用resultType="hashmap
":结果类型为HashMapresultMap="personResultMap
":定义结果映射,将数据库列映射到Java对象的属性flushCache="false
":查询执行前不清除查询缓存useCache="true
":使用查询缓存timeout="10
":查询超时时间为10秒fetchSize="256
":JDBC的fetchSize属性值,一次从数据库检索的行数为256statementType="PREPARED
" :JDBC语句类型为预编译,提高性能并防止SQL注入攻击resultSetType="FORWARD_ONLY
" :结果集类型为只向前滚动,提高性能并减少资源消耗cache="true
":启用查询结果缓存fetchScrollable="true
":启用可滚动的结果集获取,提高性能并高效访问结果集中的行fetchSizeForScrollable="500
":当使用可滚动的结果集获取时,一次从数据库检索的行数为500SELECT * FROM user WHERE id = #{id}
:SQL查询语句,从person表中根据id选择相应的行
# 1.2、selectKey参数
<selectKey
keyProperty="id"
resultType="int"
order="BEFORE"
statementType="PREPARED">
1
2
3
4
5
2
3
4
5
keyProperty
:selectKey 语句结果应该被设置到的目标属性。如果生成列不止一个,可以用逗号分隔多个属性名称。keyColumn
:返回结果集中生成列属性的列名。如果生成列不止一个,可以用逗号分隔多个属性名称。resultType
:结果的类型。通常 MyBatis 可以推断出来,但是为了更加准确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果生成列不止一个,则可以使用包含期望属性的 Object 或 Map。order
:可以设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它首先会生成主键,设置 keyProperty 再执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。statementType
:和前面一样,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 类型的映射语句,分别代表 Statement, PreparedStatement 和 CallableStatement 类型。
# 1.3、sql重复代码
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </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 user t1 cross join dept t2
</select>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 2、insert, update 和 delete
<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">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
id
:在命名空间中唯一的标识符,可以被用来引用这条语句。parameterType
:将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以根据语句中实际传入的参数计算出应该使用的类型处理器* (TypeHandler),默认值为未设置(unset)。parameterMap
:用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。flushCache
:将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。timeout
:这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。statementType
:可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。useGeneratedKeys
:(仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQLServer:这样的关系型数据库管理系统的自动递增字段),默认值:false。keyProperty
:(仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。keyColumn
:(仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。databaseId
:如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
# 3、参数补充
CRUD【增删改查】中我们已经说明了${}
和#{}
的使用方式,这里不再赘述。
参数其实还可以设置一些属性:
<!-- javaType对应Java类型,jdbcType对应数据库类型,
typeHandler对应类型处理器,可以自定义处理,也可以是枚举处理器 -->
#{sex,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
<!--
参数的“mode”属性用于指定参数的类别。这个属性的取值范围是“IN”、“OUT”和“INOUT”。
“IN”参数:输入参数,通常用于向存储过程或函数传递数据。
“OUT”参数:输出参数,通常用于从存储过程或函数接收数据。
“INOUT”参数:输入/输出参数,用于同时向存储过程或函数传递数据和接收数据。
jdbcTypeName:用于指定JDBC类型的完全限定名。
resultMap:用于指定结果映射的ID。后面详解。
-->
#{sex, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=sexMap}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4、结果映射
# 4.1、resultMap结果映射
当数据库表字段名与实体类属性名不一致时,可以通过resultMap
来映射字段名和实体类属性名。
执行效率快,开发效率低
实体类
@Data
public class User {
private int id;
private String username;
private String hashedPassword;
}
1
2
3
4
5
6
2
3
4
5
6
通过resultMap结果映射
<!-- id 就是起个名,在使用的时候用这个名就行 type 是哪个实体类 -->
<resultMap id="userResultMap" type="User">
<!--配置主键字段的对应id ,对象的唯一标识,官方解释是:为了提高mybatis的性能。建议写上。-->
<id property="id" column="user_id" />
<!-- property 写类中的属性名 column写数据库中对应的字段名-->
<result property="username" column="user_name"/>
<result property="hashedPassword" column="hashed_password"/>
</resultMap>
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password from user
where id = #{id}
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 4.2、自动结果映射
执行效率低,开发效率变快
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4.3、开启驼峰命名映射
<!-- mybatis-config.xml -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
1
2
3
4
2
3
4
数据库字段:user_id
,对应实体类中的属性:userId
。