一、定义SQL语句
(1)select 标签的使用
属性介绍:
属性 | 简介 |
id | 此命名空间中可用于引用此语句的唯一标识符。 |
parameterType | 将传递到此语句中的参数的完全限定类名称或别名。该属性是可选的,因为 MyBatis 可以计算 TypeHandler 使用的传递给语句的实际参数。默认为unset。 |
| 这是一种不推荐使用的引用外部parameterMap. 使用内联参数映射和 |
resultType | 将从该语句返回的预期类型的完全限定类名或别名。请注意,在集合的情况下,这应该是集合包含的类型,而不是集合本身的类型。使用resultType或者resultMap,而不是两者。 |
resultMap | 对外部的命名引用resultMap。结果映射是 MyBatis 最强大的特性,对它们有一个很好的理解,很多棘手的映射案例都可以解决。使用resultMap或者resultType,而不是两者。 |
flushCache | 将此设置为 true 将导致在调用此语句时刷新本地和二级缓存。默认值:false用于选择语句。 |
useCache | 将此设置为 true 将导致此语句的结果缓存在二级缓存中。默认值: true用于选择语句。 |
timeout | 这将设置驱动程序在抛出异常之前等待数据库从请求返回的秒数。默认为unset(依赖于驱动程序)。 |
fetchSize | 这是一个驱动程序提示,它将尝试使驱动程序以与此设置大小相等的行编号批量返回结果。默认为unset(依赖于驱动程序)。 |
statementType | 任何一个STATEMENT,PREPARED或CALLABLE。这会导致 MyBatis分别使用Statement, PreparedStatement或CallableStatement。默认值:PREPARED。 |
resultSetType | 任何一项FORWARD_ONLY、 SCROLL_SENSITIVE、 SCROLL_INSENSITIVE、 DEFAULT(与未设置相同)。默认为unset(依赖于驱动程序)。 |
databaseId | 如果有配置的 databaseIdProvider,MyBatis 将加载所有没有databaseId 属性或与databaseId当前匹配的语句。如果 case 相同的语句,如果发现有和没有databaseId后者,将被丢弃。 |
resultOrdered | 这仅适用于嵌套结果选择语句:如果这是真的,则假定嵌套结果被包含或组合在一起,这样当返回新的主结果行时,将不再引用前一个结果行。这允许填充嵌套结果更加内存友好。默认值: false。 |
resultSets | 这仅适用于多个结果集。它列出了语句将返回的结果集,并为每个结果集命名。名称以逗号分隔。 |
例子:
<select id="userList" parameterType="user" resultType="User">
select * from user where name =#{name}
</select>
(2)insert、delete、update标签的使用
属性介绍:
属性 | 简介 |
id | 此命名空间中可用于引用此语句的唯一标识符。 |
parameterType | 将传递到此语句中的参数的完全限定类名称或别名。该属性是可选的,因为 MyBatis 可以计算 TypeHandler 使用的传递给语句的实际参数。默认为unset。 |
| 这是一种不推荐使用的引用外部参数映射的方法。使用内联参数映射和 parameterType 属性。 |
flushCache | 将此设置为 true 将导致在调用此语句时刷新第二级缓存和本地缓存。默认值:true用于插入、更新和删除语句。 |
timeout | 这将设置驱动程序在抛出异常之前等待数据库从请求返回的最大秒数。默认为unset(依赖于驱动程序)。 |
statementType | 任何一个STATEMENT,PREPARED或CALLABLE。这会导致 MyBatis分别使用Statement, PreparedStatement或CallableStatement。默认值:PREPARED。 |
useGeneratedKeys | (仅插入和更新)这告诉 MyBatis 使用 JDBCgetGeneratedKeys方法来检索数据库内部生成的键(例如,像 MySQL 或 SQL Server 这样的 RDBMS 中的自动增量字段)。默认值:false。 |
keyProperty | (仅插入和更新)标识一个属性,MyBatis 将在其中设置由getGeneratedKeys或selectKey插入语句的子元素返回的键值。默认值:unset。如果需要多个生成的列,可以是逗号分隔的属性名称列表。 |
keyColumn | (仅插入和更新)使用生成的键设置表中列的名称。当键列不是表中的第一列时,这仅在某些数据库(如 PostgreSQL)中需要。如果需要多个生成的列,可以是逗号分隔的列名列表。 |
databaseId | 如果有配置的 databaseIdProvider,MyBatis 将加载所有没有databaseId 属性或与databaseId当前匹配的语句。如果 case 相同的语句,如果发现有和没有databaseId后者,将被丢弃。 |
例子:
<insert id="insertAuthor">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor">
update Author set
username = #{username},
password = #{password},
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor">
delete from Author where id = #{id}
</delete>
插入语句的配置规则更加丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,并且提供了多种生成方式。
首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了。例如,如果上面的 Author 表已经在 id 列上使用了自动生成,那么语句可以修改为:
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
如果你的数据库还支持多行插入, 你也可以传入一个 Author 数组或集合,并返回自动生成的主键。
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</insert>
对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。
这里有一个简单(也很傻)的示例,它可以生成一个随机 ID(不建议实际使用,这里只是为了展示 MyBatis 处理问题的灵活性和宽容度):
<insert id="insertAuthor">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
</insert>
在上面的示例中,首先会运行 selectKey 元素中的语句,并设置 Author 的 id,然后才会调用插入语句。这样就实现了数据库自动生成主键类似的行为,同时保持了 Java 代码的简洁。
selectKey 元素描述如下:
<selectKey
keyProperty="id"
resultType="int"
order="BEFORE"
statementType="PREPARED">
selectKey 元素的属性
属性 | 描述 |
keyProperty | selectKey 语句结果应该被设置到的目标属性。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | 返回结果集中生成列属性的列名。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
resultType | 结果的类型。通常 MyBatis 可以推断出来,但是为了更加准确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果生成列不止一个,则可以使用包含期望属性的 Object 或 Map。 |
order | 可以设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它首先会生成主键,设置 keyProperty 再执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。 |
statementType | 和前面一样,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 类型的映射语句,分别代表 Statement, PreparedStatement 和 CallableStatement 类型。 |
二、查询结果集
基本作用:建立SQL查询结果字段与实体属性的映射关系信息,查询的结果集转换为java对象,方便进一步操作,将结果集中的列与java对象中的属性对应起来并将值填充进去
ResultMap标签的子标签
- constructor - 用于在实例化类时,注入结果到构造方法中(后面详细说明-第五章 )
- idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
- arg - 将被注入到构造方法的一个普通结果
- id - 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
- result - 注入到字段或 JavaBean 属性的普通结果
- association - 一对一关联映射(后面详细说明-第五章 )
- collection - 一对多关联映射(后面详细说明-第五章 )
- discriminator - 使用结果值来决定使用哪个 resultMap**(未发现适用场景,不过多说明)**
- case - 基于某些值的结果映射
- 嵌套结果映射 - case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
ResultMap的属性列表
属性 | 描述 |
id | 当前命名空间中的一个唯一标识,用于标识一个结果映射。 |
type | 类的完全限定名, 或者一个类型别名(关于内置的类型别名,可以参考上面的表格)。 |
autoMapping | 如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)。 |
(1)简单映射:
<resultMap id="getStudentRM" type="EStudnet">
<id property="id" column="ID"/>
<result property="studentName" column="Name"/>
<result property="studentAge" column="Age"/>
</resultMap>
<select id="getStudent" resultMap="getStudentRM">
SELECT ID, Name, Age FROM TStudent
</select>
这个就不过多说明了
(2)高级结果映射
MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。
比如,我们如何映射下面这个语句?
<!-- 非常复杂的语句 -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
A.favourite_section as author_favourite_section,
P.id as post_id,
P.blog_id as post_blog_id,
P.author_id as post_author_id,
P.created_on as post_created_on,
P.section as post_section,
P.subject as post_subject,
P.draft as draft,
P.body as post_body,
C.id as comment_id,
C.post_id as comment_post_id,
C.name as comment_name,
C.comment as comment_text,
T.id as tag_id,
T.name as tag_name
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Post P on B.id = P.blog_id
left outer join Comment C on P.id = C.post_id
left outer join Post_Tag PT on PT.post_id = P.id
left outer join Tag T on PT.tag_id = T.id
where B.id = #{id}
</select>
你可能想把它映射到一个智能的对象模型,这个对象表示了一篇博客,它由某位作者所写,有很多的博文,每篇博文有零或多条的评论和标签。 我们先来看看下面这个完整的例子,它是一个非常复杂的结果映射(假设作者,博客,博文,评论和标签都是类型别名)。 不用紧张,我们会一步一步地来说明。虽然它看起来令人望而生畏,但其实非常简单。
<!-- 非常复杂的结果映射 -->
<resultMap id="detailedBlogResultMap" type="Blog">
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
<result property="favouriteSection" column="author_favourite_section"/>
</association>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
三、动态拼接SQL
(1)if 标签的使用
if标签通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件, 他也经常用于UPDATE语句中判断是否更新某一个字段,还可以在INSERT语句中用来判断是否插入某个字段的值
例:
<select id="getStudentListLikeName" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</select>
但是此时如果studentName是null或空字符串,此语句很可能报错或查询结果为空。此时我们使用if动态sql语句先进行判断,如果值为null或等于空字符串,我们就不进行此条件的判断。
修改为:
<select id=" getStudentListLikeName " parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<if test="studentName!=null and studentName!='' ">
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
</select>
(2)foreach 标签的使用
foreach标签主要用于构建in条件,他可以在sql中对集合进行迭代。如下:
<delete id="deleteBatch">
delete from user where id in
<foreach collection="array" item="id" index="index" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
我们假如说参数为---- int[] ids = {1,2,3,4,5} ----那么打印之后的SQL如下:
delete form user where id in (1,2,3,4,5)
释义:
collection :collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、数组、map集合,我在上面传的参数为数组,所以值为array
item : 表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
我们通常可以将之用到批量删除、添加等操作中。
(3)choose 标签的使用
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。
if是与(and)的关系,而choose是或(or)的关系。
例如下面例子,同样把所有可以限制的条件都写上,方面使用。选择条件顺序,when标签的从上到下的书写顺序:
<select id="getStudentListChooseEntity" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<where>
<choose>
<when test="studentName!=null and studentName!='' ">
ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</when>
<when test="studentSex!= null and studentSex!= '' ">
AND ST.STUDENT_SEX = #{studentSex}
</when>
<when test="studentBirthday!=null">
AND ST.STUDENT_BIRTHDAY = #{studentBirthday}
</when>
<when test="classEntity!=null and classEntity.classID !=null and classEntity.classID!='' ">
AND ST.CLASS_ID = #{classEntity.classID}
</when>
<otherwise>
</otherwise>
</choose>
</where>
</select>
四、格式化输出
(1)where
当if标签较多时,这样的组合可能会导致错误。例如,like姓名,等于指定性别等:
<!-- 查询学生list,like姓名,=性别 -->
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
WHERE
<if test="studentName!=null and studentName!='' ">
ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
<if test="studentSex!= null and studentSex!= '' ">
AND ST.STUDENT_SEX = #{studentSex}
</if>
</select>
如果上面例子,参数studentName为null或’’,则或导致此sql组合成“WHERE AND”之类的关键字多余的错误SQL。
这时我们可以使用where动态语句来解决。这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。
上面例子修改为:
<!-- 查询学生list,like姓名,=性别 -->
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<where>
<if test="studentName!=null and studentName!='' ">
ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
<if test="studentSex!= null and studentSex!= '' ">
AND ST.STUDENT_SEX = #{studentSex}
</if>
</where>
</select>
(2)set
当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。
没有使用if标签时,如果有一个参数为null,都会导致错误,如下示例:
<!-- 更新学生信息 -->
<update id="updateStudent" parameterType="StudentEntity">
UPDATE STUDENT_TBL
SET STUDENT_TBL.STUDENT_NAME = #{studentName},
STUDENT_TBL.STUDENT_SEX = #{studentSex},
STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},
STUDENT_TBL.CLASS_ID = #{classEntity.classID}
WHERE STUDENT_TBL.STUDENT_ID = #{studentID};
</update>
使用set+if标签修改后,如果某项为null则不进行更新,而是保持数据库原值。如下示例:
<!-- 更新学生信息 -->
<update id="updateStudent" parameterType="StudentEntity">
UPDATE STUDENT_TBL
<set>
<if test="studentName!=null and studentName!='' ">
STUDENT_TBL.STUDENT_NAME = #{studentName},
</if>
<if test="studentSex!=null and studentSex!='' ">
STUDENT_TBL.STUDENT_SEX = #{studentSex},
</if>
<if test="studentBirthday!=null ">
STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},
</if>
<if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">
STUDENT_TBL.CLASS_ID = #{classEntity.classID}
</if>
</set>
WHERE STUDENT_TBL.STUDENT_ID = #{studentID};
</update>
(3)trim
trim是更灵活的去处多余关键字的标签,他可以实践where和set的效果。
where例子的等效trim语句:
<!-- 查询学生list,like姓名,=性别 -->
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="studentName!=null and studentName!='' ">
ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
<if test="studentSex!= null and studentSex!= '' ">
AND ST.STUDENT_SEX = #{studentSex}
</if>
</trim>
</select>
set例子的等效trim语句:
<!-- 更新学生信息 -->
<update id="updateStudent" parameterType="StudentEntity">
UPDATE STUDENT_TBL
<trim prefix="SET" suffixOverrides=",">
<if test="studentName!=null and studentName!='' ">
STUDENT_TBL.STUDENT_NAME = #{studentName},
</if>
<if test="studentSex!=null and studentSex!='' ">
STUDENT_TBL.STUDENT_SEX = #{studentSex},
</if>
<if test="studentBirthday!=null ">
STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},
</if>
<if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">
STUDENT_TBL.CLASS_ID = #{classEntity.classID}
</if>
</trim>
WHERE STUDENT_TBL.STUDENT_ID = #{studentID};
</update>
五、配置关联关系
(1)association(一对一)
association通常用来映射一对一的关系,例如,有个类user,对应的实体类如下:(getter,setter方法省略)
private String id;//主键
private String userName;//用户姓名
有个类Article,对应的实体类如下:
private String id;//主键
private String articleTitle;//文章标题
private String articleContent;//文章内容
如果我想查询一个用户的时候,也查到他写的一篇文章,可以怎样写呢?在类user加入一个属性article
private String id;//主键
private String userName;//用户姓名
private Article article;//新增的文章属性
在user类对应的userMapper.xml这样配置
<resultMap id="userResultMap" type="test.mybatis.entity.User">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>
//这里把user的id传过去 test.mybatis.dao.articleMapper为命名空间
<association property="article" column="id" select="test.mybatis.dao.articleMapper.selectArticleByUserId"/>
</resultMap>
<select id="selectByUserId" resultMap="userResultMap" >
select * from tb_user
</select>
同时,article类对应的articleMapper.xml这样写:
<resultMap id="articleResultMap" type="test.mybatis.entity.Article">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleTitle" property="articleTitle" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleContent" property="articleContent" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>
<select id="selectArticleByUserId" parameterType="java.lang.String" resultMap="articleResultMap" >
select * from tb_article where userId=#{userId}
</select>
(2)collection(一对多)
实体类增加对应属性
private String id;//主键
private String userName;//用户姓名
private List<Article> articleList;
在user类对应的userMapper.xml这样配置
<resultMap id="userResultMap" type="test.mybatis.entity.User">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>
//这里把user的id传过去
<collection property="articleList" column="id" select="test.mybatis.dao.articleMapper.selectArticleListByUserId" />
</resultMap>
<select id="selectByUserId" resultMap="userResultMap" >
select * from tb_user
</select>
同时,article类对应的articleMapper.xml这样写:
<resultMap id="articleResultMap" type="test.mybatis.entity.Article">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleTitle" property="articleTitle" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleContent" property="articleContent" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>
<select id="selectArticleListByUserId" parameterType="java.lang.String" resultMap="articleResultMap" >
select * from tb_article where userId=#{userId}
</select>
如果我还想通过Article表另一张表,比如文章中有个fk_id,也可以像上面这样重复配置,把fk_id当做与另一张表关联的参数,那时就可以通过用户查到文章,查到文章关联的另一张表了。
(3)constructor(构造方法)
通过修改对象属性的方式,可以满足大多数的数据传输对象(Data Transfer Object, DTO)以及绝大部分领域模型的要求。但有些情况下你想使用不可变类。 一般来说,很少改变或基本不变的包含引用或数据的表,很适合使用不可变类。 构造方法注入允许你在初始化时为类设置属性的值,而不用暴露出公有方法。MyBatis 也支持私有属性和私有 JavaBean 属性来完成注入,但有一些人更青睐于通过构造方法进行注入。 constructor 元素就是为此而生的。
看看下面这个构造方法:
public class User {
//...
public User(Integer id, String username, int age) {
//...
}
//...
}
为了将结果注入构造方法,MyBatis 需要通过某种方式定位相应的构造方法。 在下面的例子中,MyBatis 搜索一个声明了三个形参的构造方法,参数类型以 java.lang.Integer, java.lang.String 和 int 的顺序给出。
<constructor>
<idArg column="id" javaType="int"/>
<arg column="username" javaType="String"/>
<arg column="age" javaType="_int"/>
</constructor>
当你在处理一个带有多个形参的构造方法时,很容易搞乱 arg 元素的顺序。 从版本 3.4.3 开始,可以在指定参数名称的前提下,以任意顺序编写 arg 元素。 为了通过名称来引用构造方法参数,你可以添加 @Param 注解,或者使用 ‘-parameters’ 编译选项并启用 useActualParamName 选项(默认开启)来编译项目。下面是一个等价的例子,尽管函数签名中第二和第三个形参的顺序与 constructor 元素中参数声明的顺序不匹配。
<constructor>
<idArg column="id" javaType="int" name="id" />
<arg column="age" javaType="_int" name="age" />
<arg column="username" javaType="String" name="username" />
</constructor>
六、sql标签与include标签
这个元素可以用来定义可重用的 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>