网站建设 技术协议,wordpress迁站到阿里云,方案设计评分标准,长沙马拉松调整为线上赛【-1】README 1#xff09;本文全文总结于 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html【0】SQL 映射文件有很少的几个顶级元素#xff08;按照它们应该被定义的顺序#xff09;#xff1a;
cache – 给定命名空间的缓存配置。cache-ref – 其他命名空间缓存配置… 【-1】README 1本文全文总结于 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html【0】SQL 映射文件有很少的几个顶级元素按照它们应该被定义的顺序
cache – 给定命名空间的缓存配置。cache-ref – 其他命名空间缓存配置的引用。resultMap – 是最复杂也是最强大的元素用来描述如何从数据库结果集中来加载对象。干货——resultMap确实很厉害 parameterMap – 已废弃老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除这里不会记录。sql – 可被其他语句引用的可重用语句块。insert – 映射插入语句update – 映射更新语句delete – 映射删除语句select – 映射查询语句 【1】select 语句1简单查询的 select 元素是非常简单的。比如select idselectPerson parameterTypeint resultTypehashmapSELECT * FROM PERSON WHERE ID #{id}
/select 对以上代码的分析Analysis这个语句被称作 selectPerson接受一个 int或 Integer类型的参数并返回一个 HashMap 类型的对象其中的键是列名值便是结果行中的对应值。注意参数符号#{id}2这就告诉 MyBatis 创建一个预处理语句参数如下所示 // Similar JDBC code, NOT MyBatis…
String selectPerson SELECT * FROM PERSON WHERE ID?;
PreparedStatement ps conn.prepareStatement(selectPerson);
ps.setInt(1,id); 3我们需要深入了解参数和结果映射 3.1select 元素有很多属性允许你配置来决定每条语句的作用细节。selectidselectPersonparameterTypeintparameterMapdeprecatedresultTypehashmapresultMappersonResultMapflushCachefalseuseCachetruetimeout10000fetchSize256statementTypePREPAREDresultSetTypeFORWARD_ONLY 3.2select attributes 如下 【2】insert, update 和 deleteinsertidinsertAuthorparameterTypedomain.blog.AuthorflushCachetruestatementTypePREPAREDkeyPropertykeyColumnuseGeneratedKeystimeout20updateidupdateAuthorparameterTypedomain.blog.AuthorflushCachetruestatementTypePREPAREDtimeout20deleteiddeleteAuthorparameterTypedomain.blog.AuthorflushCachetruestatementTypePREPAREDtimeout20 1下面就是 insertupdate 和 delete 语句的示例insert idinsertAuthorinsert into Author (id,username,password,email,bio)values (#{id},#{username},#{password},#{email},#{bio})
/insertupdate idupdateAuthorupdate Author setusername #{username},password #{password},email #{email},bio #{bio}where id #{id}
/updatedelete iddeleteAuthordelete from Author where id #{id}
/delete 2插入语句的配置规则更加丰富有多种生成方式2.1首先如果你的数据库支持自动生成主键的字段比如 MySQL 和 SQL Server那么你可以设置 useGeneratedKeys”true”然后再把 keyProperty 设置到目标属性上就OK了。insert idinsertAuthor useGeneratedKeystruekeyPropertyidinsert into Author (username,password,email,bio)values (#{username},#{password},#{email},#{bio})
/insert 2.2若数据库支持多行插入你可以传递一个数组或List 集合对象 并检索出 自动生成的key insert idinsertAuthor useGeneratedKeystruekeyPropertyidinsert into Author (username, password, email, bio) valuesforeach itemitem collectionlist separator,(#{item.username}, #{item.password}, #{item.email}, #{item.bio})/foreach
/insert 【3】sql 1intro 这个元素可以被用来定义可重用的 SQL 代码段可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如 干货——定义sql并对其复用引用 sql iduserColumns ${alias}.id,${alias}.username,${alias}.password /sql 1.1这个 SQL 片段可以被包含在其他语句中例如 select idselectUsers resultTypemapselectinclude refiduserColumnsproperty namealias valuet1//include,include refiduserColumnsproperty namealias valuet2//includefrom some_table t1cross join some_table t2
/select 1.2属性值可以用于包含的refid属性或者包含的字句里面的属性值例如 sql idsometable${prefix}Table
/sqlsql idsomeincludefrominclude refid${include_target}/
/sqlselect idselect resultTypemapselectfield1, field2, field3include refidsomeincludeproperty nameprefix valueSome/property nameinclude_target valuesometable//include
/select 【4】参数Parameters1参数映射insert idinsertUser parameterTypeUserinsert into users (id, username, password)values (#{id}, #{username}, #{password})
/insert 对以上代码的分析Analysis如果 User 类型的参数对象传递到了语句中id、username 和 password 属性将会被查找然后将它们的值传入预处理语句的参数中。 2这点对于向语句中传参是比较好的而且又简单不过参数映射的功能远不止于此。 2.1首先像 MyBatis 的其他部分一样参数也可以指定一个特殊的数据类型。 #{property,javaTypeint,jdbcTypeNUMERIC} Attention 如果 null 被当作值来传递对于所有可能为空的列JDBC Type 是需要的。你可以自己通过阅读预处理语句的 setNull() 方法的 JavaDocs 文档来研究这种情况。 2.2为了以后定制类型处理方式你也可以指定一个特殊的类型处理器类或别名比如 #{age,javaTypeint,jdbcTypeNUMERIC,typeHandlerMyTypeHandler} 2.3对于数值类型还有一个小数保留位数的设置来确定小数点后保留的位数。 #{height,javaTypedouble,jdbcTypeNUMERIC,numericScale2} 3最后mode 属性允、你指定 INOUT 或 INOUT 参数。如果参数为 OUT 或 INOUT参数对象属性的真实值将会被改变就像你在获取输出参数时所期望的那样。如果 mode 为 OUT或 INOUT而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR)你必须指定一个 resultMap 来映射结果集到参数类型。要注意这里的 javaType 属性是可选的如果左边的空白是 jdbcType 的 CURSOR 类型它会自动地被设置为结果集。 #{department, modeOUT, jdbcTypeCURSOR, javaTypeResultSet, resultMapdepartmentResultMap} 4字符串替换默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值比如?。这样做更安全更迅速通常也是首选做法不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串。比如像 ORDER BY你可以这样来使用 ORDER BY ${columnName} Attention 以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的会导致潜在的 SQL 注入攻击因此要么不允许用户输入这些字段要么自行转义并检验。干货——引入了SQL注入攻击 【5】Result Maps 1intro ResultMap 的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系。 2看个荔枝 简单映射语句的示例了,但没有明确的 resultMap。比如: select idselectUsers resultTypemapselect id, username, hashedPasswordfrom some_tablewhere id #{id}
/select 对以上代码的分析Analysis这样一个语句简单作用于所有列被自动映射到 HashMap 的键上,这由 resultType 属性 指定。 3problem solution 3.1problem这在很多情况下是有用的,但是 HashMap 不能很好描述一个领域模型。 3.2solution那样你的应 用程序将会使用 JavaBeans 或 POJOs(Plain Old Java Objects,普通 Java 对象)来作为领域 模型。MyBatis 对两者都支持。看看下面这个 JavaBean: package com.someapp.model;
public class User {private int id;private String username;private String hashedPassword;public int getId() {return id;}public void setId(int id) {this.id id;}public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getHashedPassword() {return hashedPassword;}public void setHashedPassword(String hashedPassword) {this.hashedPassword hashedPassword;}
} 3.2.1这样的一个 JavaBean 可以被映射到结果集,就像映射到 HashMap 一样简单。 select idselectUsers resultTypecom.someapp.model.Userselect id, username, hashedPasswordfrom some_tablewhere id #{id}
/select 3.2.2要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。比如:干货——设定别名 !-- In mybatis-config.xml file --
typeAlias typecom.someapp.model.User aliasUser/!-- In SQL Mapping XML file --
select idselectUsers resultTypeUserselect id, username, hashedPasswordfrom some_tablewhere id #{id}
/select 4MyBatis 会在幕后自动创建一个 ResultMap,基于属性名来映射列到 JavaBean 的属性上。 5problemsolution 5.1problem如果列名没有精确匹配 5.2solution2 solutions 5.2.1你可以在列名上使用 select 字句的别名(一个 基本的 SQL 特性)来匹配标签。比如: select idselectUsers resultTypeUserselectuser_id as id,user_name as userName,hashed_password as hashedPasswordfrom some_tablewhere id #{id}
/select 5.2.2让我们来看看最后一个示例中 外部的 resultMap 是什么样子的,这也是解决列名不匹配的另外一种方式。 resultMap iduserResultMap typeUserid propertyid columnuser_id /result propertyusername columnuser_name/result propertypassword columnhashed_password/
/resultMap 5.2.2.1引用它的语句使用 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如: selectidselectUsersresultMapuserResultMapselect user_id, user_name, hashed_passwordfrom some_tablewhere id #{id}
/select 【5.1】高级结果映射 1problemsolutions 1.1problemMyBatis 创建的一个想法数据库不用永远是你想要的或需要它们是什么样的。而我们 最喜欢的数据库最好是第三范式或 BCNF 模式,但它们有时不是。如果可能有一个单独的 数据库映射,所有应用程序都可以使用它,这是非常好的,但有时也不是 1.2solutions结果映射就是 MyBatis 提供处理这个问题的答案 2problemsolutions 2.1problem我们如何映射下面这个语句? !-- Very Complex Statement --
select idselectBlogDetails resultMapdetailedBlogResultMapselectB.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_namefrom Blog Bleft outer join Author A on B.author_id A.idleft outer join Post P on B.id P.blog_idleft outer join Comment C on P.id C.post_idleft outer join Post_Tag PT on PT.post_id P.idleft outer join Tag T on PT.tag_id T.idwhere B.id #{id}
/select 2.2solutions下面是一个完整的复杂结果映射例子 (假设作者, 博客, 博文, 评论和标签都是类型的别名) 我们来看看, 。 但是不用紧张, 我们会一步一步来说明。 !-- Very Complex Result Map --
resultMap iddetailedBlogResultMap typeBlogconstructoridArg columnblog_id javaTypeint//constructorresult propertytitle columnblog_title/association propertyauthor javaTypeAuthorid propertyid columnauthor_id/result propertyusername columnauthor_username/result propertypassword columnauthor_password/result propertyemail columnauthor_email/result propertybio columnauthor_bio/result propertyfavouriteSection columnauthor_favourite_section//associationcollection propertyposts ofTypePostid propertyid columnpost_id/result propertysubject columnpost_subject/association propertyauthor javaTypeAuthor/collection propertycomments ofTypeCommentid propertyid columncomment_id//collectioncollection propertytags ofTypeTag id propertyid columntag_id//collectiondiscriminator javaTypeint columndraftcase value1 resultTypeDraftPost//discriminator/collection
/resultMap 对以上代码的分析Analysis A1resultMap constructor - 类在实例化时,用来注入结果到构造方法中 idArg -ID 参数;标记结果作为 ID 可以帮助提高整体效能arg -注入到构造方法的一个普通结果 id –一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能result –注入到字段或 JavaBean 属性的普通结果association –一个复杂的类型关联;许多结果将包成这种类型 嵌入结果映射 – 结果映射自身的关联,或者参考一个 collection –复杂类型的集 嵌入结果映射 – 结果映射自身的集,或者参考一个 discriminator –使用结果值来决定使用哪个结果映射 case –基于某些值的结果映射 嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。 【5.2】id result id propertyid columnpost_id/
result propertysubject columnpost_subject/ 对以上代码的分析Analysis 这些是结果映射最基本内容。id 和 result 都映射一个单独列的值到简单数据类型(字符 串,整型,双精度浮点数,日期等)的单独属性或字段。 这两者之间的唯一不同是 id 表示的结果将是当比较对象实例时用到的标识属性。这帮 助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射) 。 1id 和 result 属性list 如下所示 【5.3】支持的 JDBC 类型 【5.4】构造方法 constructoridArg columnid javaTypeint/arg columnusername javaTypeString/
/constructor 对以上代码的分析Analysis idArg是为了 和 id 元素 区分开 1看看下面这个构造函数 public class User {//...public User(int id, String username) {//...}
//...
} 对以上代码的分析Analysis A1当创建一个构造方法元素时,保证参数是按顺序 排列的,而且数据类型也是确定的。 A2该元素的属性值 和 result 和 id 元素的属性值相同 【5.5】关联 association propertyauthor columnblog_author_id javaTypeAuthorid propertyid columnauthor_id/result propertyusername columnauthor_username/
/association 1intro 关联即表关联 2关联中不同的是你需要告诉 MyBatis 如何加载关联。MyBatis 在这方面会有两种不同的 方式: way1嵌套查询通过执行另外一个 SQL 映射语句来返回预期的复杂类型。 way2嵌套结果使用嵌套结果映射来处理重复的联合结果的子集。首先, 让我们来查看这个元素的属性。所有的你都会看到,它和普通的只由 select 和 resultMap 属性的结果映射不同。 【5.6】关联的嵌套查询 1看个荔枝 resultMap idblogResult typeBlogassociation propertyauthor columnauthor_id javaTypeAuthor selectselectAuthor/
/resultMapselect idselectBlog resultMapblogResultSELECT * FROM BLOG WHERE ID #{id}
/selectselect idselectAuthor resultTypeAuthorSELECT * FROM AUTHOR WHERE ID #{id}
/select 对以上代码的分析Analysis 我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的 author 属性。 其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。 这种方式很简单, 但是对于大型数据集合和列表将不会表现很好。 问题就是我们熟知的 “N1 查询问题”。概括地讲,N1 查询问题可以是这样引起的:干货——引入了N1 查询问题 你执行了一个单独的 SQL 语句来获取结果列表(就是“1”)。对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。 这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。 MyBatis 能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消 耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,你会调用所有的延迟加 载,这样的行为可能是很糟糕的。 所以还有另外一种方法。干货——引入了 延迟加载 【5.7】关联的嵌套结果 1看个荔枝这个是一个非常简单的示例 来说明它如何工作。代替了执行一个分离的语句,我们联合博客表和作者表在一起,就像: selectidselectBlogresultMapblogResultselectB.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_biofrom Blog B left outer join Author A on B.author_id A.idwhere B.id #{id}
/select 1.1现在我们可以映射这个结果: resultMap idblogResult typeBlogid propertyid columnblog_id /result propertytitle columnblog_title/association propertyauthor columnblog_author_id javaTypeAuthor resultMapauthorResult/
/resultMapresultMap idauthorResult typeAuthorid propertyid columnauthor_id/result propertyusername columnauthor_username/result propertypassword columnauthor_password/result propertyemail columnauthor_email/result propertybio columnauthor_bio/
/resultMapspan stylecolor: rgb(0, 0, 136); font-family: Monaco, Menlo, Consolas, Courier New, monospace; font-size: 16px; line-height: 24px; background-color: rgb(245, 245, 245); /span 1.2现在,上面的示例用了外部的结果映射元素来映射关联。这使得 Author 结果映射可以 重用。然而,如果你不需要重用它的话,或者你仅仅引用你所有的结果映射合到一个单独描 述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例干货——引入了嵌套结果 resultMap idblogResult typeBlogid propertyid columnblog_id /result propertytitle columnblog_title/association propertyauthor javaTypeAuthorid propertyid columnauthor_id/result propertyusername columnauthor_username/result propertypassword columnauthor_password/result propertyemail columnauthor_email/result propertybio columnauthor_bio//association
/resultMap 2如果这个博客是由多个作者联合作者撰写的话查询语句select 映射为这个样子 selectidselectBlogresultMapblogResultselectB.id as blog_id,B.title as blog_title,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,CA.id as co_author_id,CA.username as co_author_username,CA.password as co_author_password,CA.email as co_author_email,CA.bio as co_author_biofrom Blog Bleft outer join Author A on B.author_id A.idleft outer join Author CA on B.co_author_id CA.idwhere B.id #{id}
/select 2.1调用作者 Author 的resultMap定义如下 resultMap idauthorResult typeAuthorid propertyid columnauthor_id/result propertyusername columnauthor_username/result propertypassword columnauthor_password/result propertyemail columnauthor_email/result propertybio columnauthor_bio/
/resultMap 2.2因为结果集中的 列名 不同于 resultMap 中的 列名你需要指定 columnPrefix 以复用resultMap来映射 联合作者结果 resultMap idblogResult typeBlogid propertyid columnblog_id /result propertytitle columnblog_title/association propertyauthorresultMapauthorResult /association propertycoAuthorresultMapauthorResultcolumnPrefixco_ /
/resultMap 【5.8】集合 collection propertyposts ofTypedomain.blog.Postid propertyid columnpost_id/result propertysubject columnpost_subject/result propertybody columnpost_body/
/collection 1看个荔枝 我们来继续上面的示例一个博客只有一个作者。但是博客有很多文章。在博客类中, 这可以由下面这样的写法来表示: private ListPost posts; 【5.8.1】集合的嵌套查询 1intro 使用嵌套查询来为博客加载文章 resultMap idblogResult typeBlogcollection propertyposts javaTypeArrayList columnid ofTypePost selectselectPostsForBlog/
/resultMapselect idselectBlog resultMapblogResultSELECT * FROM BLOG WHERE ID #{id}
/selectselect idselectPostsForBlog resultTypeBlogSELECT * FROM POST WHERE BLOG_ID #{id}
/select 对以上代码的分析Analysis A1首先,你应 该注意我们使用的是集合元素。然后要注意那个新的“ofType”属性。这个属性用来区分 JavaBean(或字段)属性类型和集合包含的类型来说是很重要的。所以你可以读出下面这个 映射: collection propertyposts javaTypeArrayList columnid ofTypePost selectselectPostsForBlog/ 读作: “在 Post 类型的 ArrayList 中的 posts 的集合。” A2javaType 属性是不需要的,因为 MyBatis 在很多情况下会为你算出来。所以你可以缩短 写法: collection propertyposts columnid ofTypePost selectselectPostsForBlog/ 【5.8.2】集合的嵌套结果 1至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性 2看个荔枝 select idselectBlog resultMapblogResultselectB.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 Bleft outer join Post P on B.id P.blog_idwhere B.id #{id}
/select 2.1我们又一次联合了博客表和文章表,而且关注于保证特性,结果列标签的简单映射。现 在用文章映射集合映射博客,可以简单写为: resultMap idblogResult typeBlogid propertyid columnblog_id /result propertytitle columnblog_title/collection propertyposts ofTypePostid propertyid columnpost_id/result propertysubject columnpost_subject/result propertybody columnpost_body//collection
/resultMap 2.2同样,要记得 id 元素的重要性,如果你不记得了,请阅读上面的关联部分。 2.3同样, 如果你引用更长的形式允许你的结果映射的更多重用, 你可以使用下面这个替代 的映射: resultMap idblogResult typeBlogid propertyid columnblog_id /result propertytitle columnblog_title/collection propertyposts ofTypePost resultMapblogPostResult columnPrefixpost_/
/resultMapresultMap idblogPostResult typePostid propertyid columnid/result propertysubject columnsubject/result propertybody columnbody/
/resultMap 【5.9】鉴别器switch in java discriminator javaTypeint columndraftcase value1 resultTypeDraftPost/
/discriminator 1intro 鉴别器非常容易理 解,因为它的表现很像 Java 语言中的 switch 语句。 2看个荔枝 定义鉴别器指定了 column 和 javaType 属性。 列是 MyBatis 查找比较值的地方。 JavaType 是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)。比如: resultMap idvehicleResult typeVehicleid propertyid columnid /result propertyvin columnvin/result propertyyear columnyear/result propertymake columnmake/result propertymodel columnmodel/result propertycolor columncolor/discriminator javaTypeint columnvehicle_typecase value1 resultMapcarResult/case value2 resultMaptruckResult/case value3 resultMapvanResult/case value4 resultMapsuvResult//discriminator
/resultMap 对以上代码的分析Analysis A1 在这个示例中, MyBatis 会从结果集中得到每条记录, 然后比较它的 vehicle 类型的值。如果它匹配任何一个鉴别器的实例,那么就使用这个实例指定的结果映射。 A2如果没有任何 一个实例相匹配,那么 MyBatis 仅仅使用鉴别器块外定义的结果映射。所以,如果 carResult 按如下声明: resultMap idcarResult typeCarresult propertydoorCount columndoor_count /
/resultMap A3那么只有 doorCount 属性会被加载。这步完成后完整地允许鉴别器实例的独立组,尽管 和父结果映射可能没有什么关系。这种情况下,我们当然知道 cars 和 vehicles 之间有关系, 如 Car 是一个 Vehicle 实例。因此,我们想要剩余的属性也被加载。我们设置的结果映射的 简单改变如下。干货——想要剩余的属性也被加载使用继承extend resultMap idcarResult typeCar extendsvehicleResultresult propertydoorCount columndoor_count /
/resultMap A4现在 vehicleResult 和 carResult 的属性都会被加载了。 3尽管曾经有些人会发现这个外部映射定义会多少有一些令人厌烦之处。 因此还有另外一 种语法来做简洁的映射风格。比如: resultMap idvehicleResult typeVehicleid propertyid columnid /result propertyvin columnvin/result propertyyear columnyear/result propertymake columnmake/result propertymodel columnmodel/result propertycolor columncolor/discriminator javaTypeint columnvehicle_typecase value1 resultTypecarResultresult propertydoorCount columndoor_count //casecase value2 resultTypetruckResultresult propertyboxSize columnbox_size /result propertyextendedCab columnextended_cab //casecase value3 resultTypevanResultresult propertypowerSlidingDoor columnpower_sliding_door //casecase value4 resultTypesuvResultresult propertyallWheelDrive columnall_wheel_drive //case/discriminator
/resultMap 【6】自动映射 1intro 通常数据库列使用大写单词命名单词间用下划线分隔而java属性一般遵循驼峰命名法。 为了在这两种命名方式之间启用自动映射需要将 mapUnderscoreToCamelCase设置为true。 2自动映射甚至在特定的result map下也能工作。在这种情况下对于每一个result map,所有的ResultSet提供的列 如果没有被手工映射则将被自动映射。自动映射处理完毕后手工映射才会被处理。 在接下来的例子中 id 和 userName列将被自动映射 hashed_password 列将根据配置映射。干货——自动映射处理完毕后手工映射才会被处理 3看个荔枝 selectidselectUsersresultMapuserResultMapselectuser_id as id,user_name as userName,hashed_passwordfrom some_tablewhere id #{id}
/select resultMap iduserResultMap typeUserresult propertypassword columnhashed_password/
/resultMap 4There are three auto-mapping levels:3个自动映射级别 NONE - disables auto-mapping. Only manually mapped properties will be set.PARTIAL - will auto-map results except those that have nested result mappings defined inside (joins).默认级别FULL - auto-maps everything. 4.1将PARTIAL 设置为默认级别的原因The default value is PARTIAL, and it is so for a reason. When FULL is used auto-mapping will be performed when processing join results and joins retrieve data of several different entities in the same row hence this may result in undesired mappings. 4.2To understand the risk have a look at the following sample: selectidselectBlogresultMapblogResultselectB.id,B.title,A.username,from Blog B left outer join Author A on B.author_id A.idwhere B.id #{id}
/select resultMap idblogResult typeBlogassociation propertyauthor resultMapauthorResult/
/resultMapresultMap idauthorResult typeAuthorresult propertyusername columnauthor_username/
/resultMap Analysis of the sample) With this result map both Blog and Author will be auto-mapped. But note that Author has an id property and there is a column named id in the ResultSet so Authors id will be filled with Blogs id, and that is not what you were expecting. So use the FULL option with caution. 4.3Regardless of the auto-mapping level configured you can enable or disable the automapping for an specific ResultMap by adding the attribute autoMapping to it: 干货——添加 autoMapping属性 pre namecode classhtmlresultMap iduserResultMap typeUser autoMappingfalseresult propertypassword columnhashed_password/
/resultMap 【7】缓存 1intro 默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行: cache/ 对以上代码的分析Analysis 这个简单语句的效果如下: 映射语句文件中的所有 select 语句将会被缓存。映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。 2 所有的这些属性都可以通过缓存元素的属性来修改。比如: pre namecode classhtmlcacheevictionFIFOflushInterval60000size512readOnlytrue/ 对以上代码的分析Analysis 这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。 3可用的收回策略有: LRU – 最近最少使用的:移除最长时间不被使用的对象。默认策略FIFO – 先进先出:按对象进入缓存的顺序来移除它们。SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。WEAK – 弱引用: 更积极地移除基于垃圾收集器状态和弱引用规则的对象。 Supplement supplement1flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒 形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 supplement2size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的 可用内存资源数目。默认值是 1024。 supplement3readOnly(只读)属性 可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓 存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。 【7.1】使用自定义缓存 1intro 你也可以通过实现你自己的缓存或为其他第三方缓存方案 创建适配器来完全覆盖缓存行为。干货——自定义缓存 cache typecom.domain.something.MyCustomCache/ 对以上代码的分析Analysis A1type 属 性指 定的 类必 须实现 org.mybatis.cache.Cache 接口。 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();
} 2看个荔枝 要配置你的缓存, 简单和公有的 JavaBeans 属性来配置你的缓存实现, 而且是通过 cache 元素来传递属性,比如, 下面代码会在你的缓存实现中调用一个称为 “setCacheFile(String file)” 的方法: cache typecom.domain.something.MyCustomCacheproperty namecacheFile value/tmp/my-custom-cache.tmp/
/cache 3记得缓存配置和缓存实例是绑定在 SQL 映射文件的命名空间是很重要的。因此,所有 在相同命名空间的语句正如绑定的缓存一样。 语句可以修改和缓存交互的方式, 或在语句的 语句的基础上使用两种简单的属性来完全排除它们。默认情况下,语句可以这样来配置: select ... flushCachefalse useCachetrue/
insert ... flushCachetrue/
update ... flushCachetrue/
delete ... flushCachetrue/ 对以上代码的分析Analysis 因为那些是默认的,你明显不能明确地以这种方式来配置一条语句。相反,如果你想改 变默认的行为,只能设置 flushCache 和 useCache 属性。比如,在一些情况下你也许想排除 从缓存中查询特定语句结果,或者你也许想要一个查询语句来刷新缓存。相似地,你也许有 一些更新语句依靠执行而不需要刷新缓存。干货——如果你想改 变默认的行为,只能设置 flushCache 和 useCache 属性 【7.2】参照缓存 1回想一下上一节内容, 这个特殊命名空间的唯一缓存会被使用或者刷新相同命名空间内 的语句。也许将来的某个时候,你会想在命名空间中共享相同的缓存配置和实例。在这样的 情况下你可以使用 cache-ref 元素来引用另外一个缓存。 cache-refnamespacecom.someone.application.data.SomeMapper/