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

  • id="selectPerson": Mapper方法名称,对应selectPerson方法
  • parameterType="int":参数类型为int
  • parameterMap="deprecated":参数映射已过时,可能不再使用
  • resultType="hashmap":结果类型为HashMap
  • resultMap="personResultMap":定义结果映射,将数据库列映射到Java对象的属性
  • flushCache="false":查询执行前不清除查询缓存
  • useCache="true":使用查询缓存
  • timeout="10":查询超时时间为10秒
  • fetchSize="256":JDBC的fetchSize属性值,一次从数据库检索的行数为256
  • statementType="PREPARED" :JDBC语句类型为预编译,提高性能并防止SQL注入攻击
  • resultSetType="FORWARD_ONLY" :结果集类型为只向前滚动,提高性能并减少资源消耗
  • cache="true":启用查询结果缓存
  • fetchScrollable="true":启用可滚动的结果集获取,提高性能并高效访问结果集中的行
  • fetchSizeForScrollable="500":当使用可滚动的结果集获取时,一次从数据库检索的行数为500
  • SELECT * 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

  • 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、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

  • 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

# 4、结果映射

# 4.1、resultMap结果映射

当数据库表字段名与实体类属性名不一致时,可以通过resultMap来映射字段名和实体类属性名。

执行效率快,开发效率低

实体类

@Data
public class User {
  private int id;
  private String username;
  private String hashedPassword;
}
1
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

# 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

# 4.3、开启驼峰命名映射

<!-- mybatis-config.xml -->
<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
1
2
3
4

数据库字段:user_id,对应实体类中的属性:userId