mybatis中配置文件介绍2

SQL映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache–配置给定命名空间的缓存。

cache-ref–从其他命名空间引用缓存配置。

resultMap–最复杂,也是最重要的元素,用来描述如何从数据库结果集映射到对象。

sql–可以重用的SQL块,也可以被其他语句引用。

insert–映射插入语句
update–映射更新语句
delete–映射删除语句
select–映射查询语句
Select语句
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID=#{id}
</select>
#{id}:这就告诉MyBatis创建一个预处理语句参数。使用JDBC,这样的一个参数在SQL中会由一个“?”来标识,并被传递到一个新的预处理语句中。

id:在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType:将会传入这条语句的参数类的完全限定名或别名。
resultType:从这条语句中返回的期望类型的类的完全限定名或别名。注意集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用resultType或resultMap,但不能同时使用。
resultMap:命名引用外部的resultMap。返回map是MyBatis最重要的特性,对其有一个很好的理解的话,很多复杂映射的情形就能被解决了。使用resultMap或resultType,但不能同时使用。
useGeneratedKeys:(仅对insert有用)这会告诉MyBatis使用JDBC的getGeneratedKeys方法来取出由数据库(比如:像MySQL和SQLServer这样的数据库管理系统的自动递增字段)内部生成的主键。默认值:false。
keyProperty:(仅对insert有用)标记一个属性,MyBatis会通过getGeneratedKeys或者通过insert语句的selectKey子元素设置它的值。默认:不设置。
keyColumn:(仅对insert有用)标记一个属性,MyBatis会通过getGeneratedKeys或者通过insert语句的selectKey子元素设置它的值。默认:不设置。

首先,如果你的数据库支持自动生成主键的字段(比如MySQL和SQLServer),那么你可以设置useGeneratedKeys=”true”,而且设置keyProperty到你已经做好的目标属性上。例如,如果上面的Author表已经对id使用了自动生成的列类型,那么语句可以修改为:

<insert id="insertAuthor" parameterType="domain.blog.Author" useGeneratedKeys="true"
keyProperty="id">
insert into Author(username,password,email,bio)
values(#{username},#{password},#{email},#{bio})
</insert>

<selectKey
keyProperty="id"
resultType="int"
order="BEFORE"
statementType="PREPARED">

selectKey
keyPropertyselectKey:语句结果应该被设置的目标属性。
resultType:结果的类型。MyBatis通常可以算出来,但是写上也没有问题。MyBatis允许任何简单类型用作主键的类型,包括字符串。
order:这可以被设置为BEFORE或AFTER。如果设置为BEFORE,那么它会首先选择主键,设置keyProperty然后执行插入语句。如果设置为AFTER,那么先执行插入语句,然后是selectKey元素-这和如Oracle数据库相似,可以在插入语句中嵌入序列调用。
statementType:和前面的相同,MyBatis支持STATEMENT,PREPARED和CALLABLE语句的映射类型,分别代表PreparedStatement和CallableStatement类型。

sql:
create sequence crm_seq start with 1 increment by 10 maxvalue 100

@Insert("INSERT INTO users(id,name,password,role_id,enabled)"
+"VALUES(crm_seq.nextval,#{name},#{password},#{role.id},#{enabled})")
void save (User user);

sql
这个元素可以被用来定义可重用的SQL代码段,可以包含在其他语句中。比如:
<sql id="userColumns">id,username,password</sql>
这个SQL片段可以被包含在其他语句中,例如:
<select id="selectUsers" parameterType="int" resultType="hashmap">
select <include refid="userColumns"/>
from some_table
where id=#{id}
</select>

<insert id="insertAuthor" parameterType="domain.blog.Author">
<select KeykeyProperty="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代码变得复杂。

Parameters
Mybatis中,参数的元素是非常重要的,可以传入简单数据类型,当然也可以传入复杂数据类型。例如:
<insert id="insertUser" parameterType="User">
insert into users(id,username,password)
values(#{id},#{username},#{password})
</insert>

如果User类型的参数对象传递到了语句中,username和password属性将会被查找,id、然后它们的值就被传递到预处理语句的参数中。
这点对于传递参数到语句中非常好。但是对于参数映射也有一些其他的特性。
首先,像MyBatis的其他特性,参数可以指定一个确定的数据类型。
#{property,javaType=int,jdbcType=NUMERIC}

像MyBatis的剩余部分,javaType通常可以从参数对象中来确定,除非对象是一个HashMap。那么javaType应该被确定来保证使用正确类型处理器。

注意:如果null被当作值来传递,对于所有可能为空的列,JDBCType是需要的。也可以通过阅读PreparedStatement.setNull()方法的JavaDocs文档来研究它。
为了以后自定义类型处理器,你可以指定一个确定的类型处理器类(或别名),比如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
尽管它看起来繁琐,但是实际上是你很少设置它们其中之一。

对于数值类型,对于决定有多少数字是相关的,有一个数值范围。
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
最后,mode属性允许你指定IN,OUT或INOUT参数。如果参数为OUT或INOUT,参数对象属性的真实值将会被改变,就像你期望你需要几个输出参数。如果mode为OUT(或INOUT),而且jdbcType为CURSOR(也就是Oracle的REFCURSOR),你必须指定一个resultMap来映射结果集到参数类型。要注意这里的javaType属性是可选的,如果左边的空白是jdbcType的CURSOR类型,它会自动地被设置为结果集。
#{department,
mode=OUT,
jdbcType=CURSOR,
javaType=ResultSet,
resultMap=departmentResultMap}
字符串替换
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速,也是首选的做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDERBY,你可以这样来使用:
ORDERBY${columnName}
重要:接受从用户输入的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。

ResultMap,Mybatis中最强大的元素,作用:对结果集映射。
<select id=”selectUsers” parameterType=”int” resultType=”hashmap”>
select id,username,hashedPassword
from some_table
where id=#{id}
</select>
这样一个语句简单作用于所有列被自动映射到HashMap的键上,这由resultType属性指定。这在很多情况下是有用的,但是HashMap不能很好描述一个领域模型。应用程序将会使用JavaBeans或POJOs(PlainOldJavaObjects,普通Java对象)来作为领域模型。MyBatis对两者都支持。

<select id=”selectUsers” parameterType=”int”
resultType=”User”>
select id,username,hashedPassword
from some_table
where id=#{id}
</select>
如上情况,MyBatis会在幕后自动创建一个ResultMap,基于属性名来映射列到JavaBean的属性上。如果列名没有精确匹配,可以在列名上使用select字句的别名(一个标准的SQL特性)来匹配标签。比如:

<select id=”selectUsers” parameterType=”int”  resultType=”User”>
select
user_id asid”,
user_name as “userName”,
hashed_password as “hashedPassword”
from some_table
where id=#{id}
</select>

第二种配置,不使用列别名
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
引用它的语句使用resultMap属性就行了(注意我们去掉了resultType属性)。比如:
<select id=”selectUsers” parameterType=”int”
resultMap=”userResultMap”>
selectuser_id,user_name,hashed_password
from some_table
where id=#{id}
</select>

ResultMap子元素介绍
resultMap
constructor–类在实例化时,用来注入结果到构造方法中
idArg–ID参数;标记结果作为ID可以帮助提高整体效能
arg–注入到构造方法的一个普通结果
idid表示的结果将是当比较对象实例时用到的标识属性。
result–注入到字段或JavaBean属性的普通结果
association–一个复杂的类型关联;许多结果将包成这种类型
嵌入结果映射–结果映射自身的关联,或者参考一个
collection–复杂类型的集
嵌入结果映射–结果映射自身的集,或者参考一个
discriminator–使用结果值来决定使用哪个结果映射
case–基于某些值的结果映射
嵌入结果映射–这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

在idresult的结果映射中,两个子元素
property:映射到列结果的字段或属性。如果匹配JavaBeans的属性,那么就会使用。否则MyBatis将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,可以这样映射:
“username”或者“address.street.number”。
column:从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会传递给resultSet.getString(columnName)方法参数中相同的字符串。
javaType:一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。
jdbcType:所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,需要指定这个类型-但仅仅对可能为空的值。
typeHandler:覆盖默认的类型处理器。

嵌套关联

<resultMap id=”blogResult” type=”Blog”>
<association property="author" column="blog_author_id" javaType="Author" select=”selectAuthor”/>
</resultMap>
<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID=#{id}
</select>
<select id=”selectAuthor” parameterType=”int” resultType="Author">
SELECT * FROM AUTHOR WHERE ID=#{id}
</select>

如上情况有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描述了“selectAuthor”语句应该被用来加载它的author属性。其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。这种方式很简单,但是对于大型数据集合和列表将不会表现很好。问题就是我们熟知的“N+1查询问题”。概括地讲,N+1查询问题可以是这样引起的:
执行了一个单独的SQL语句来获取结果列表(就是“+1”)。
对返回的每条记录,你执行了一个查询语句来匹配每个加载细节(就是“N”)。
MyBatis能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,调用所有的延迟加
载,这样的行为可能是很糟糕的。

另一种方式:

关联的嵌套
<select id="selectBlog" parameterType="int" resultMap="blogResult">
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
From Blog B
left outer join Author A on B.author_id=A.id
where B.id=#{id}
</select>

注意这个联合查询,以及采取别名来确保所有结果唯一而且清晰。这使得映射非常简单。现在我们可以映射这个结果:
<resultMap id="blogResult" type="Blog">
<id property=”blog_id” column="id"/>
<result property="title" column="blog_title"/>
<association property="author" column="blog_author_id" javaType="Author" resultMap=”authorResult”/>
</resultMap>

<resultMap id="authorResult" type="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"/>
</resultMap>
非常重要:在嵌套结果映射中(即resultMap的id属性)id元素扮演了非常重要的角色。应该通常指定一个或多个属性,它们可以用来唯一标识结果。实际上就是如果你不使用它(id元素),但是会产生一个严重的性能问题,不过MyBatis仍然可以正常工作。选择的属性越少越好,它们可以唯一地标识结果。主键就是一个显而易见的选择(即便是联合主键)。

集合的嵌套查询
首先,让我们看看使用嵌套查询来为博客加载文章。
<resultMap id=”blogResult”type=”Blog”>
<collection property="posts" javaType=”ArrayList” column="blog_id" ofType="Post" select=”selectPostsForBlog”/>
</resultMap>
<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID=#{id}
</select>
<select id=”selectPostsForBlog” parameterType=”int” resultType="Author">
SELECT * FROM POST WHERE BLOG_ID=#{id}
</select>
使用的是集合元素Collection,另外“ofType”属性,区分JavaBean(或字段)属性类型和集合包含的类型。
<collection property="posts" javaType=”ArrayList” column="blog_id" ofType="Post" select=”selectPostsForBlog”/>
读作:“在Post类型的ArrayList中的posts的集合。”
javaType属性是不需要的,因为MyBatis在很多情况下会算出来。所以你可以缩短写法:
<collection property="posts" column="blog_id" ofType="Post" select=”selectPostsForBlog”/>

实例一:
<select id="selectBlog" parameterType="int" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id=P.blog_id
where B.id=#{id}
</select>

结果集合的映射

<resultMap id="blogResult" type="Blog">
<id property=”id” column="blog_id"/>
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>

同样,要记得id元素的重要性,当然如上的情况还可以做如下修改,使得代码进一步得到重用。

<resultMap id="blogResult"type="Blog">
<id property=”id” column="blog_id"/>
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post" resultMap=”blogPostResult”/>
</resultMap>
<resultMap id="blogPostResult" type="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</resultMap>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值