MyBatis Mapper XML 文件 02
?
<select id="selectBlogDetails" parameterType="int" 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>
?Ok,看看对于上面复杂的语句,对应的ResultMap为:
<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>?
?
resultMap
<id property="id" column="post_id"/><result property="subject" column="post_subject"/>
?
Id and Result Attributes
属性
描述
property
映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同 的 JavaBeans 的属性,那么就
会使用。否则 MyBatis 将会寻找给定名称 property 的字段。这两种情形你可以使用通常点式的复
杂属性导航。比如,你 可以这样映射一些东西: “username” ,或者映射到一些复杂的东西:
?“address.street.number” 。
column
从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会 传递给 resultSet.getString
(columnName)方法参数中相同的字符串。
javaType
一个 Java 类的完全限定名,或一个类型别名(参加上面内建类型别名 的列表) 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。 然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的行为。
jdbcType
在这个表格之后的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅 仅需要对插入,更新和删
除操作可能为空的列进行处理。这是 JDBC jdbcType 的需要,而不是 MyBatis 的。如果你直接使
用 JDBC 编程,你需要指定 这个类型-但仅仅对可能为空的值。
typeHandler
我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默 认的类型处理器。这个属性值
是类的完全限定名或者是一个类型处理 器的实现,或者是类型别名。
<constructor> <idArg column="id" javaType="int"/> <arg column="username" javaType="String"/></constructor>
?这里需要注意id和username的顺序问题,不能颠倒。
public class User { //... public User(int id, String username) { //... }//...}?
?
<association property="author" column="blog_author_id" javaType=" Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/></association>
?
属性
描述
column
来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字
符串是相同的。 column 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过
?column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2
?以参数对象形式来设置给目标嵌套查询语句。
select
另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被
传递给目标 select 语句作为参数。表格后面 有一个详细的示例。 select 注 意 : 要 处 理 复 合 主
?键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递
给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
<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>
?
属性
描述
resultMap
这是结果映射的 ID,可以映射关联的嵌套结果到一个合适的对象图中。这 是一种替代方法来调
用另外一个查询语句。这允许你联合多个表来合成到 resultMap 一个单独的结果集。这样的结
果集可能包含重复,数据的重复组需要被分 解,合理映射到一个嵌套的对象图。为了使它变得容
易,MyBatis 让你“链 接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后 面也
有一个示例。
columnPrefix
当加入多个表,你将不得不使用列别名,以避免重复列名在ResultSet。 指定columnPrefix允许
您映射到一个外部等栏目resultMap
<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="id" column="blog_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="blogResult" type="Blog"> <id property="id" column="blog_id" /> <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"/> </association></resultMap>
?
<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="Blog"> SELECT * FROM POST WHERE BLOG_ID = #{id}</select>
?
<collection property="posts" javaType="ArrayList" column="blog_id" ofType="Post" select="selectPostsForBlog"/>
?
<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>?
同样, 如果你引用更长的形式允许你的结果映射的更多重用, 你可以使用下面这个替代 的映射:
<resultMap id="blogResult" type="Blog"> <id property="id" column="blog_id" /> <result property="title" column="blog_title"/> <collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/></resultMap><resultMap id="blogPostResult" type="Post"> <id property="id" column="id"/> <result property="subject" column="subject"/> <result property="body" column="body"/></resultMap>
?
<discriminator javaType="int" column="draft"> <case value="1" resultType="DraftPost"/></discriminator>
?
<resultMap id="vehicleResult" type="Vehicle"> <id property="id" column="id" /> <result property="vin" column="vin"/> <result property="year" column="year"/> <result property="make" column="make"/> <result property="model" column="model"/> <result property="color" column="color"/> <discriminator javaType="int" column="vehicle_type"> <case value="1" resultMap="carResult"/> <case value="2" resultMap="truckResult"/> <case value="3" resultMap="vanResult"/> <case value="4" resultMap="suvResult"/> </discriminator></resultMap>?
?
<cache/>
?
映射语句文件中的所有 select 语句将会被缓存。
映射语句文件中的所有insert,update 和 delete 语句会刷新缓存。
缓存会使用 Least RecentlyUsed(LRU,最近最少使用的)算法来收回。
根据时间表(比如 no FlushInterval,没有刷新间隔), 缓存不会以任何时间顺序来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
?
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
readOnly(只读)属性可以被设置为 true或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
<cache type="com.domain.something.MyCustomCache"/>
?
public interface Cache { String getId(); int getSize(); void putObject(Object key, Object value); Object getObject(Object key); boolean hasKey(Object key); Object removeObject(Object key); void clear(); ReadWriteLock getReadWriteLock();}?
?
<cache type="com.domain.something.MyCustomCache"> <property name="cacheFile" value="/tmp/my-custom-cache.tmp"/></cache>?
<select ... flushCache="false" useCache="true"/><insert ... flushCache="true"/><update ... flushCache="true"/><delete ... flushCache="true"/>
?
因为那些是默认的,你明显不能明确地以这种方式来配置一条语句。相反,如果你想改变默认的行为,只能设置 flushCache 和 useCache 属性。比如,在一些情况下你也许想排除从缓存中查询特定语句结果,或者你也许想要一个查询语句来刷新缓存。相似地,你也许有一些更新语句依靠执行而不需要刷新缓存。