疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

MyBatis连载深入Mapper XML映射文件


 

 
MyBatis的真正强大之处在于它的映射语句,这也是它的魔力所在。由于它的功能异常强大,映射器的XML文件就显得相对简单。如果拿它跟具有相同功能的JDBC代码进行对比,你会立即发现省掉了将近95%的代码。MyBatis就是针对SQL构建的,并且比普通的方法做得更好。
SQL映射文件常用的元素如下:
select。映射查询语句。
insert。映射插入语句。
update。映射更新语句。
delete。映射删除语句。
sql。可被其他语句引用的可重用语句块。
cache。给定命名空间的缓存配置。
cache-ref。其他命名空间缓存配置的引用。
resultMap。最复杂也是最强大的元素,用来描述如何从数据库结果集中加载对象。
 
9.3.1 select
select元素用来映射查询语句,它是MyBatis中最常用的元素之一。
执行简单查询的select元素是非常简单的。例如:
 
<select id="selectUser" parameterType="int" resultType="hashmap">
  SELECT * FROM TB_USER WHERE ID = #{id}
</select>
复制代码
 
这个语句被称作selectUser,其接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,HashMap中的键是列名,值便是结果行中的对应值。
注意参数符号#{id},这是告诉MyBatis创建一个预处理语句参数。通过JDBC,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中。以上MyBatis配置文件执行时会生成如下JDBC代码:
 
String selectUser = "SELECT * FROM TB_USER WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectUser);
ps.setInt(1,id);
复制代码
 
select元素有很多属性可以配置,它们用来决定每条语句的作用细节。例如:
 
<select
  id=" selectUser"
  parameterType="int"
  resultType="hashmap"
  resultMap="userResultMap"
  flushCache="false"
  useCache="true"
  timeout="10000"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">
复制代码
 
select元素的属性描述如下:
id。在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType。将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
resultType。从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。返回时可以使用resultType或resultMap,但不能同时使用。
resultMap。外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。返回时可以使用 resultMap 或 resultType,但不能同时使用。
flushCache。如果设置为 true,则任何时候只要语句被调用,都会导致本地缓存和二级缓存都被清空,默认值为false。
useCache。如果设置为 true,将会导致本条语句的结果被二级缓存,在select 元素当中默认值为 true。
timeout。这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
fetchSize。这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。
statementType。值为STATEMENT、PREPARED或CALLABLE。这会让MyBatis分别使用JDBC中的Statement、PreparedStatement或CallableStatement,默认值为PREPARED。
resultSetType。结果集的类型,值为FORWARD_ONLY、SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE,默认值为unset(依赖驱动)。
databaseId。如果配置了databaseIdProvider,MyBatis会加载所有的不带databaseId或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered。这个设置仅针对嵌套结果select语句适用:如果为true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生对前面结果集引用的情况。这就使得在获取嵌套的结果集时不至于导致内存不够用。默认值为false。
resultSets。这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的
 
9.3.2 insert、update和delete
insert、update和delete元素用来映射DML语句,是 MyBatis 中最常用的元素之一。
insert、update和delete元素配置和select非常接近。例如:
 
<insert
  id="insertUser"
  parameterType="org.fkit.domain.User"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">
 
<update
  id="updateUser"
  parameterType="org.fkit.domain.User "
  flushCache="true"
  statementType="PREPARED"
  timeout="20">
 
<delete
  id="deleteUser"
  parameterType="org.fkit.domain.User "
  flushCache="true"
  statementType="PREPARED"
  timeout="20">
复制代码
 
insert、update 和 delete元素的属性大多和select一致,它们特有的属性描述如下:
useGeneratedKeys。(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来获取由数据库内部生成的主键(比如,像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值为false。
keyProperty。(仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认为unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
keyColumn。(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅对某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列时需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
下面是insert、update和delete语句的示例:
 
<insert id="insertUser">
  insert into TB_USER (id,username,password,email,address)
  values (#{id},#{username},#{password},#{email},#{address})
</insert>
 
<update id="updateUser">
  update TB_USER set
    username = #{username},
    password = #{password},
    email = #{email},
    address = #{address}
  where id = #{id}
</update>
 
<delete id="deleteUser">
  delete from TB_USER where id = #{id}
</delete>
复制代码
 
而插入语句的配置规则更加丰富,因为在插入语句执行时很多时候是需要返回插入成功的数据生成的主键值的,所以<insert.../>元素里面有一些额外的属性和子元素用来处理主键的生成,而且根据数据库的主键生成策略不同,配置也有多种方式。
首先,如果数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么可以设置 useGeneratedKeys="true",然后再把 keyProperty 设置到目标属性上就可以了(一般会设置到id属性上)。例如,如果上面的 TB_USER 表已经对 id 使用了自动生成的列类型,那么语句可以修改为:
 
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
  insert into TB_USER (username,password,email,address)
  values (#{username},#{password},#{email},#{address})
</insert>
复制代码
 
对于不支持自动生成类型的数据库(比如Oracle)或可能不支持自动生成主键的JDBC驱动来说,MyBatis 有另外一种方法来生成主键。
 
<insert id="insertUser">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select SEQUENCE_TB_USER.nextval as id from dual
  </selectKey>
  insert into TB_USER
    (id, username, password, email,address)
  values
    (#{id}, #{username}, #{password}, #{email}, #{address})
</insert>
复制代码
 
在上面的示例中,selectKey 元素将会首先运行,其通过查询SEQUENCE序列,TB_USER 的 id 会被设置,然后插入语句会被调用。
selectKey 元素描述如下:
 
<selectKey
  keyProperty="id"
  resultType="int"
  order="BEFORE"
  statementType="PREPARED">
复制代码
keyProperty。selectKey语句结果应该被设置的目标属性(一般会设置到id属性上)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
keyColumn。匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
resultType。结果的类型。MyBatis 通常可以推算出来,但是为了更加确定,建议明确写出。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。
order。可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素。
statementType。与前面相同,MyBatis支持STATEMENT、PREPARED和CALLABLE语句的映射类型,分别代表Statement、PreparedStatement 和 CallableStatement 类型。
 
9.3.3 sql
sql元素可以被用来定义可重用的SQL代码段,可以包含在其他语句中。它可以被静态地(在加载参数时)参数化。不同的属性值通过包含的实例发生变化。例如:
 
<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>
  from some_table t1
</select>
复制代码
 
属性值可以用于包含的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>
复制代码
 
9.3.4 参数(Parameters)
前面的所有语句中所见到的都是简单参数的例子,实际上参数是 MyBatis 非常强大的元素。对于简单参数的使用,大多数情况下参数都很少,例如:
 
<select id="selectUsers" parameterType="int" resultType="User">
  select id, username, password
  from users
  where id = #{id}
</select>
复制代码
 
上面的这个示例说明了一个非常简单的命名参数映射。参数类型被设置为 int,这样这个参数就可以被设置成任何内容。原生的类型或简单数据类型(比如整型和字符串),因为没有相关属性,它会完全用参数值来替代。
但是,如果传入一个复杂的对象(比如User),行为就会有一点不同了。例如:
 
<insert id="insertUser" parameterType="User">
  insert into users (id, username, password)
  values (#{id}, #{username}, #{password})
</insert>
复制代码
 
如果User类型的参数对象被传递到了语句中,如#{id}语句则会查找参数对象User的id属性,#{username}和#{password}也是一样,然后将它们的值传入预处理语句的参数中。
 
【阅读原文】