Mybatis3 (2)xml映射文件

SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

  • cache – 给定命名空间的缓存配置。
  • cache-ref – 其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

select

查询

<select id="selectPerson" parameterType="int" resultType="hashmap">SELECT * FROM PERSON WHERE ID = #{id}
</select>

下面就是 insert,update 和 delete 语句的示例

<insert id="insertAuthor">insert into Author (id,username,password,email,bio)values (#{id},#{username},#{password},#{email},#{bio})
</insert><update id="updateAuthor">update Author setusername = #{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了

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

对不支持自动生成主键的JDBC驱动,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 会被设置,然后插入语句会被调用。

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><include refid="userColumns"><property name="alias" value="t2"/></include>from some_table t1cross join some_table t2
</select>

属性值也可以被用在 include 元素的 refid 属性里<include refid="${include_target}"/>或include内部语句中${prefix}Table

参数(Parameters)

<insert id="insertUser" parameterType="User">insert into users (id, username, password)values (#{id}, #{username}, #{password})
</insert>

如果User类型的参数对象传递到了语句中,id、username 和 password 属性将会被查找。

大多时候你只须简单地指定属性名,其他的事情 MyBatis 会自己去推断,顶多要为可能为空的列指定 jdbcType。

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}

更多选项设置:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Parameters

字符串替换

默认情况,使用 #{} 会导致PreparedStatement参数创建,并安全设置参数。首选!
有时想插入一个不转义的字符串,如:

ORDER BY ${columnName}

注意:用这种方式不安全,可能导致sql注入,要么不允许用户输入这些字段,要么自行转义验证。

Result Maps

resultMap 元素是 MyBatis 中最重要最强大的元素。用来支持程序使用 JavaBean 或 POJO(Plain Old Java Objects,普通 Java 对象)作为领域模型。

例如下面配置映射到User实体中

<select id="selectUsers" resultType="com.someapp.model.User">select id, username, hashedPasswordfrom some_tablewhere id = #{id}
</select>

类型别名可以帮助你不用输入类的完全限定名

<!-- In mybatis-config.xml file -->
<typeAlias type="com.someapp.model.User" alias="User"/><!-- In SQL Mapping XML file -->
<select id="selectUsers" resultType="User">select id, username, hashedPasswordfrom some_tablewhere id = #{id}
</select>

Mybatis会创建一个ResultMap,映射到javaBean中。如果没有匹配上,可以再select语句中使用别名

<select id="selectUsers" resultType="User">selectuser_id             as "id",user_name           as "userName",hashed_password     as "hashedPassword"from some_tablewhere 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" resultMap="userResultMap">select user_id, user_name, hashed_passwordfrom some_tablewhere id = #{id}
</select>

总结:resultMap可以用来解决数据库列名与属性没有匹配的问题。如果足够了解它,就不需要显示配置它。

高级结果映射

<!-- 超复杂的 Result Map -->
<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>

解析:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps

构造方法

public class User {//...public User(Integer id, String username, int age) {//...}
//...
}

将结果注入构造方法,Mybatis需要通过某种方式定位相应构造方法。constructor 元素就是为此而生的。

<constructor><idArg column="id" javaType="int"/><arg column="username" javaType="String"/><arg column="age" javaType="_int"/>
</constructor>

从版本 3.4.3 开始,可以在指定参数名称的前提下,以任意顺序编写 arg 元素。可以添加@Param注解做到

<constructor><idArg column="id" javaType="int" name="id" /> <!--name是javaBean中属性,column是数据库中字段--><arg column="age" javaType="_int" name="age" /><arg column="username" javaType="String" name="username" />
</constructor>

如果类中存在名称和类型相同的属性,那么可以省略 javaType 。

关联

<association property="author" column="blog_author_id" javaType="Author"><id property="id" column="author_id"/><result property="username" column="author_username"/>
</association>

关联的嵌套查询

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

我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的 author 属性。
其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单,但是对于大型数据集合和列表表现不好,原因是我们熟悉的“N+1 查询问题”

  • 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
  • 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

Mybatis能延时加载是好事,但是加载完后立即调用所有延迟加载,就很糟糕。

有另外一种方法。

关联的嵌套结果

<select id="selectBlog" resultMap="blogResult">selectB.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>

注意这个联合查询, 使用唯一而且清晰的名字来重命名。 使映射非常简单。

<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>

在上面,authorResult 用来加载作者实例。现在,上面的示例用了外部的结果映射元素来映射关联。这使得 Author 结果映射可以 重用

非常重要: id元素在嵌套结果映射中扮演着非 常重要的角色。 不指定唯一标志属性,会有严重的性能问题。

如果不需要映射到单独的结果映射中,也可以嵌套结果映射。

<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>

集合

<collection property="posts" ofType="domain.blog.Post"><id property="id" column="post_id"/><result property="subject" column="post_subject"/><result property="body" column="post_body"/>
</collection>

和关联相同,不同处:

private List<Post> posts;

集合的嵌套查询

首先,让我们看看使用嵌套查询来为博客加载文章。

<resultMap id="blogResult" type="Blog"><collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>
</resultMap><select id="selectBlog" resultMap="blogResult">SELECT * FROM BLOG WHERE ID = #{id}
</select><select id="selectPostsForBlog" resultType="Post">SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

关注这段

<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostsForBlog"/>

读作:“在Post类型的ArrayList中的posts的集合”。

集合的嵌套结果

至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性
详细介绍:http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps
你的应用在找到最佳方法前要一直进行的单元测试和性 能测试。

鉴别器

  <discriminator javaType="int" column="draft"><case value="1" resultType="DraftPost"/></discriminator>

有时一个单独的数据库查询也许返回很多不同 (但是希望有些关联) 数据类型的结果集。 鉴别器元素就是被设计来处理这个情况的, 还有包括类的继承层次结构。和switch语句类似。

自动映射

如果数据库字段名和javaBean属性名不一致,要将 mapUnderscoreToCamelCase设置为true

例如:

<select id="selectUsers" resultMap="userResultMap">selectuser_id             as "id",user_name           as "userName",hashed_passwordfrom some_tablewhere id = #{id}
</select>
<resultMap id="userResultMap" type="User"><result property="password" column="hashed_password"/>
</resultMap>

上面的例子中,id和userName和javaBean中属性一致,被自动映射了。而hashed_password在resultMap中映射了字段和属性,所以在结果中也能取到值。

有三种自动映射等级:

  • NONE - 禁用自动映射。仅设置手动映射属性。
  • PARTIAL(默认) - 将自动映射结果除了那些有内部定义内嵌结果映射的(joins).
  • FULL - 自动映射所有。

缓存

一级缓存是SQLSession级别的缓存,换出的数据只在SQLSession内有效。
二级缓存是mapper级别的缓存,同一个namespace公用这个缓存,所以对SQLSession是共享的

一级缓存

1.第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来

2.第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率

注意事项:

  • 如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前SqlSession缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
  • 当一个SqlSession结束后那么他里面的一级缓存也就不存在了,mybatis默认是开启一级缓存,不需要配置
  • mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。例如:-1242243203:1146242777:winclpt.bean.userMapper.getUser:0:2147483647:select * from user where id=?:19

二级缓存

二级缓存是mapper级别的缓存。也就是同一个namespace的mapper.xml,当多个SQLSession使用同一个mapper操作数据库,得到的数据会缓存在同一个二级缓存中。

具体流程:
  1.当一个sqlseesion执行了一次select后,在关闭此session的时候,会将查询结果缓存到二级缓存
  2.当另一个sqlsession执行select时,首先会在他自己的一级缓存中找,如果没找到,就回去二级缓存中找,找到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能

注意事项:
   如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前mapper缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读。

开启二级缓存:
confg.xml

<settings><setting name="cacheEnabled" value="true"/>默认是false:关闭二级缓存
<settings>

userMapper.xml

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/> 当前mapper下所有语句开启二级缓存

配置了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,返回的对象是只读。
若想禁用某select语句的二级缓存,添加userCache="false"

<select id="getCountByName" parameterType="java.util.Map" resultType="INTEGER" statementType="CALLABLE" useCache="false">

可用的收回策略有:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

使用自定义缓存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330944.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面向对象进阶

第一章 类 1.1 如何定义类 类的定义格式如下: 修饰符 class 类名 {// 1.成员变量&#xff08;属性&#xff09;// 2.成员方法 (行为) // 3.构造方法 &#xff08;初始化类的对象数据的&#xff09; }例如: public class Student {// 1.成员变量public String name ;public c…

foreach 循环详解

译自&#xff1a;http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html考虑如下代码&#xff08;方式一&#xff09;&#xff1a;迭代一个 collection 集合对象&#xff0c;然后删除集合元素void cancelAll(Collection<TimerTask> c) {for (Iterator&l…

jvm系列(六):Java服务GC参数调优案例

转载自 jvm系列(六):Java服务GC参数调优案例本文介绍了一次生产环境的JVM GC相关参数的调优过程&#xff0c;通过参数的调整避免了GC卡顿对JAVA服务成功率的影响。 这段时间在整理jvm系列的文章&#xff0c;无意中发现本文&#xff0c;作者思路清晰通过步步分析最终解决问题。我…

Mybatis3(3)动态 SQL

可以利用动态SQL摆脱凭借SQL语句的痛苦。 MyBatis 3 大大精简了元素种类&#xff0c;现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。 ifchoose (when, otherwise)trim (where, set)foreach if 动态 SQL 通常要做的事情是…

jvm系列(七):jvm调优-工具篇

转载自 jvm系列(七):jvm调优-工具篇16年的时候花了一些时间整理了一些关于jvm的介绍文章,到现在回顾起来还是一些还没有补充全面&#xff0c;其中就包括如何利用工具来监控调优前后的性能变化。工具做为图形化界面来展示更能直观的发现问题&#xff0c;另一方面一些耗费性能的分…

如何不用 List.clear() 方法 就清空 list 中的 所有元素(中兴面试)

import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List;// 涛哥 1609251501 // 如何不用 List.clear() 方法 就清空 list 中的 所有元素. public class MyList {public static void main(String[] args) {List<String>…

mybatis-spring 入门到实例

入门 安装 在pom.xml中导入mybatis-spring.jar包 快速入门 要把spring和mybatis一起使用&#xff0c;需要定义两样东西&#xff1a;SqlsessionFactory 和 至少一个数据库映射器类。 SqlSessionFactoryBean 是用于创建 SqlSessionFactory 的&#xff0c;需要一个Datasource…

在 eclipse 中 设置 jvm 的 运行时目录

然而 在 eclipse中 类所在包的目录是项目所在目录的 孙子目录 而不是 父目录&#xff1b;所以&#xff0c;如果要运行 诸如 chapter18.className这样的类 就需要 将 运行时目录设置为 项目目录/src 目录才行。

jvm系列(九):如何优化Java GC

转载自 jvm系列(九):如何优化Java GC「译」本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇《How to Tune Java Garbage Collection》,本文的作者是韩国人&#xff0c;写在JDK 1.8发布之前&#xff0c;虽然有些地方有些许过时&…

关闭json引用的方式

https://www.cnblogs.com/zjrodger/p/4630237.html 【具体方案】 1、如果你用的是FastJson&#xff0c;首先要关闭FastJson的“循环引用检测”特性。 2、如果你不想修改实体之间的关系&#xff0c;则将代码&#xff1a;“JSONField(serializefalse)”添加在下列方法中 public …

Redis学习记录

Redis简介 Redis是一个高性能的key-value非关系型数据库&#xff0c;可以存键&#xff08;key&#xff09;与5中不同类型的值&#xff08;value&#xff09;之间的映射&#xff08;mapping&#xff09;。 支持存储的value类型包括&#xff1a;String&#xff08;字符串&#…

jvm系列(十):教你如何成为Java的OOM Killer

转载自 jvm系列(十):教你如何成为Java的OOM Killer前言 虽然事隔半年&#xff0c;当时排查线上OOM事故的过程记忆犹新&#xff0c;每一个步骤都历历在目&#xff0c;感谢业务组、系统部、压测组、监控与应急部对架构组的强力支持&#xff0c;得以让这个Java内存问题水落石出&am…

java 程序的初始化顺序是怎样的?

【0】README 1&#xff09;本文 转自“ java 程序员面试笔试宝典”&#xff0c; 这个书有点意思&#xff1b; 【1】java程序初始化遵循三个原则&#xff08;rule&#xff09; r1&#xff09;静态变量 优先于 非静态变量&#xff1b; r2&#xff09;父类优先于子类进行初始化&a…

操作符

直接常量 double: 111d,111D 二进制&#xff1a;前缀为0b 十六进制&#xff1a;前缀为0x或0X&#xff0c;后面最大9位。 八进制&#xff1a;前缀为0&#xff0c;后面最大7位。 按位操作符 与&#xff08;&&#xff09;&#xff1a; 或&#xff08;||&#xff09;&#x…

jvm系列(十一):Java 8-从持久代到metaspace

转载自 jvm系列(十一):Java 8-从持久代到metaspaceJava 8介绍了一些新语言以及运行时新特点。其中一个特点便是完全移除了持久代(PermGen)&#xff0c;自从Oracle公司发布了JDK1.7后就已经宣布了这个决定。还有比如内部字符串&#xff0c;从JDK1.7开始就从持久代移除了&#xf…

我的控制反转,依赖注入和面向切面编程的理解

感谢http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/ 的供图1.什么是控制&#xff1f; 如下图所示&#xff0c;我们看到了 软件系统中 对象的 高耦合现象。全体齿轮的转动由一个对象来控制&#xff0c;如类B。2.什么是 控制反转&#xff1f; 是用来对对象进行解耦。借助第…

在Spring Boot中使用切面统一处理自定义的异常

最近我们将项目的一个单独模块提取了一个微服务&#xff0c;这个微服务主要负责其他系统的接入。目的是发布主项目的时候不会影响到其他系统接入。在提取出的微服务中&#xff0c;需要定义一个正常返回的报文和异常返回的报文。正常返回报文就是正常业务返回的数据报文&#xf…

Java 8的新特性—终极版

转载自 Java 8的新特性—终极版 1. 简介 毫无疑问&#xff0c;Java 8是Java自Java 5&#xff08;发布于2004年&#xff09;之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。在本文中我们将学习这些新特性&#xff0c;并用实际的例子说明在…

ReviewForJob——java虚拟机的垃圾回收策略(个人总结)

理解jvm的垃圾回收策略&#xff0c;需要解决以下3个问题问题1&#xff1a;哪些内存需要回收&#xff1f;问题2&#xff1a;什么时候进行回收&#xff1f;问题3&#xff1a;怎样来回收&#xff1f;【解决问题1】哪些内存需要回收&#xff1f;jvm的内存区域有5大块&#xff1a;1&…

使用静态代理模式实现公用的报表导出功能

先聊一下什么是代理模式&#xff1f; 代理模式 给某个对象提供一个代理对象&#xff0c;并由代理独享控制对原对象的引用。什么意思呢&#xff1f;代理模式就有点像我们生活中常见的中介。 举个例子&#xff0c;我想买辆二手车&#xff0c;第一种方式是自己去找车源&#xff…