Mybatis学习笔记

Mybatis学习笔记

一、Mybatis是什么?

在介绍MyBatis之前先简单了解几个概念:ORM,JPA。

ORM(Object-Relationship-Mapping):是对象关系映射的意思,它是一种思想,是指将数据库中的每一行数据用对象的形式表现出来。

JPA(Java-Persistence-API):是Java持久化接口的意思,它是JavaEE关于ORM思想的一套标准接口,仅仅是一套接口,不是具体的实现。

MyBatis是一个实现了JPA规范的用来连接数据库并对其进行增删改查操作的开源框架(就和传统的JDBC一样,就是个连接数据库的东西),其实,它底层就是一个JDBC封装的组件。MyBatis的前身是Ibatis,Ibatis创建与2002年最初为Apache下面的一个开源项目,2010迁移到google code下面并改名为MyBatis。

MyBatis虽然实现了JPA但是它并不是一个完完全全的ORM组件,而是一个基于SQL开发的半ORM组件。

而Hibernate是一个完完全全的ORM组件,它是完全基于对象来操作数据库中的记录,并不和MyBatis一样是一个假把式。

 

二、Mybatis mapper的使用

Mappers中包含很多个mapper,其中mapper里面是链接sql语句的配置文件;

Mapper映射器是Mybatis中的核心工具,也是Mybatis的核心功能。Mybatis映射器由mapper接口和mapper xml配置文件组成。

SELECT  select元素执行查询,根据parameterType指定参数类型,根据resultType指定返回类型。

<select id="getRole" parameterType="java.lang.Integer" resultType="Role">  

<span style="white-space:pre;"> </span>select id, role_name roleName, note from role where id = #{id}  

</select>

这个查询语句,根据ID值查询相应的记录,返回字段名为id、rolenName、note,Mybatis自动将他们组装成一个Role对象实例作为返回结果。

我们还可以通过resultMap映射结果集。

 <resultMap type="Role" id="roleResultMap">  

<id property="id" column="id"/>  

<result property="roleName" column="role_name"/>  

<result property="note" column="note"/>  

</resultMap>  



<select id="getRole" parameterType="java.lang.Integer" resultMap="roleResultMap">  

select id, role_name, note from role where id = #{id}  

</select>

这里定义了一个id为roleResultMap的映射规则resultMap,它的type属性为Role。其中id元素即为数据库表中的主键(可以有多个联合主键)、result元素为其它简单类型(当然还有复杂类型)。property属性是javabean中的属性名,column是数据库中对应的字段名。指定select元素的resultMap属性值为roleResultMap(注意不是resultType,resultType指定返回类型, 而resultMap指定使用哪一个resultMap的映射规则,二者不能同时存在)。这样Mybatis同样可以完成数据库记录到javabean的自动映射。

select 元素有很多属性允许你配置,来决定每条语句的作用细节。

<select

  id="selectPerson"

  parameterType="int"

  parameterMap="deprecated"

  resultType="hashmap"

  resultMap="personResultMap"

  flushCache="false"

  useCache="true"

  timeout="10000"

  fetchSize="256"

  statementType="PREPARED"

  resultSetType="FORWARD_ONLY">

Select Attributes

属性

描述

id

在命名空间中唯一的标识符,可以被用来引用这条语句。

parameterType

将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset

parameterMap

这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数映射和 parameterType 属性。

resultType

从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType resultMap,但不能同时使用。

resultMap

外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap resultType,但不能同时使用。

flushCache

将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false

useCache

将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true

timeout

这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。

fetchSize

这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。

statementType

STATEMENTPREPARED CALLABLE 的一个。这会让 MyBatis 分别使用 StatementPreparedStatement CallableStatement,默认值:PREPARED

resultSetType

FORWARD_ONLYSCROLL_SENSITIVE SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。

databaseId

如果配置了 databaseIdProviderMyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

resultOrdered

这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false

resultSets

这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。

 

三、缓存

Mybatis包含一个非常强大的查询缓存特性;它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。

默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:

<cache/>

字面上看就是这样。这个简单语句的效果如下:

·        映射语句文件中的所有 select 语句将会被缓存。

·        映射语句文件中的所有 insert,update delete 语句会刷新缓存。

·        缓存会使用 Least RecentlyUsed(LRU,最近最少使用的)算法来收回。

·        根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序来刷新。

·        缓存会存储列表集合或对象(无论查询方法返回什么) 1024 个引用。

·        缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

所有的这些属性都可以通过缓存元素的属性来修改。比如:

<cache

  eviction="FIFO"

  flushInterval="60000"

  size="512"

  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。

可用的收回策略有:

·        LRU – 最近最少使用的:移除最长时间不被使用的对象。

·        FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

·        SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

·        WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

默认的是 LRU

四、动态 SQL

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

·        if

·        choose (when, otherwise)

·        trim (where, set)

·        foreach

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:

<selectid="findActiveBlogWithTitleLike"

     resultType="Blog">

  SELECT * FROM BLOG

  WHERE state = ‘ACTIVE’

  <iftest="title !=null">

    AND title like #{title}

  </if>

</select>

这条语句提供了一种可选的查找文本功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会对“title”一列进行模糊查找并返回 BLOG 结果(细心的读者可能会发现,“title”参数值是可以包含一些掩码或通配符的)。

如果希望通过“title”“author”两个参数进行可选搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。

<selectid="findActiveBlogLike"

     resultType="Blog">

  SELECT * FROM BLOG WHERE state = ‘ACTIVE’

  <iftest="title !=null">

    AND title like #{title}

  </if>

  <iftest="author !=null and author.name != null">

    AND author_name like #{author.name}

  </if>

</select>

choose, when,otherwise

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找的情形,若两者都没有提供,就返回所有符合条件的 BLOG(实际情况可能是由管理员按一定策略选出 BLOG 列表,而不是返回大量无意义的随机结果)。

<selectid="findActiveBlogLike"

     resultType="Blog">

  SELECT * FROM BLOG WHERE state = ‘ACTIVE’

  <choose>

    <whentest="title !=null">

      AND title like #{title}

    </when>

    <whentest="author !=null and author.name != null">

      AND author_name like #{author.name}

    </when>

    <otherwise>

      AND featured = 1

    </otherwise>

  </choose>

</select>

trim,where, set

前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在回到“if”示例,这次我们将“ACTIVE = 1”也设置成动态的条件,看看会发生什么。

<selectid="findActiveBlogLike"

     resultType="Blog">

  SELECT * FROM BLOG

  WHERE

  <iftest="state !=null">

    state = #{state}

  </if>

  <iftest="title !=null">

    AND title like #{title}

  </if>

  <iftest="author !=null and author.name != null">

    AND author_name like #{author.name}

  </if>

</select>

如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:

SELECT * FROM BLOG

WHERE

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:

SELECT * FROM BLOG

WHERE

AND title like someTitle

这个查询也会失败。这个问题不能简单地用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不会再写出这种语句了。

MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:

<selectid="findActiveBlogLike"

     resultType="Blog">

  SELECT * FROM BLOG

  <where>

    <iftest="state !=null">

         state = #{state}

    </if>

    <iftest="title != null">

        AND title like #{title}

    </if>

    <iftest="author !=null and author.name != null">

        AND author_name like #{author.name}

    </if>

  </where>

</select>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”“OR”where 元素也会将它们去除。

如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

<trimprefix="WHERE"prefixOverrides="AND |OR">

  ...

</trim>

prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

类似的用于动态更新语句的解决方案叫做 setset 元素可以用于动态包含需要更新的列,而舍去其它的。比如:

<updateid="updateAuthorIfNecessary">

  update Author

    <set>

      <iftest="username!= null">username=#{username},</if>

      <iftest="password!= null">password=#{password},</if>

      <iftest="email !=null">email=#{email},</if>

      <iftest="bio !=null">bio=#{bio}</if>

    </set>

  where id=#{id}

</update>

这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)

若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:

<trimprefix="SET"suffixOverrides=",">

  ...

</trim>

注意这里我们删去的是后缀值,同时添加了前缀值。

foreach

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:

<selectid="selectPostIn"resultType="domain.blog.Post">

  SELECT *

  FROM POST P

  WHERE ID in

  <foreachitem="item"index="index"collection="list"

      open="("separator=","close=")">

        #{item}

  </foreach>

</select>

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。

注意 你可以将任何可迭代对象(如 ListSet 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,这样就能提高已创建的映射文件的利用效率。

五、  SqlSessions

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器和管理事务。我们会概括讨论一下 SqlSession 本身,但是首先我们还是要了解如何获取一个 SqlSession 实例。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法。而 SqlSessionFactory 本身是由SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或手动配置 Java 代码来创建 SqlSessionFactory。

从 XML 中构建 SqlSessionFactory。

每个基于 MyBatis 的应用都是以一个SqlSessionFactory 的实例为中心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。

XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 file:// URL 形式的文件路径来配置。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。

String resource ="org/mybatis/example/mybatis-config.xml";
InputStream inputStream =Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =newSqlSessionFactoryBuilder().build(inputStream);

XML 配置文件(configuration XML)中包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。XML 配置文件的详细内容后面再探讨,这里先给出一个简单的示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environmentsdefault="development">
    <environmentid="development">
      <transactionManagertype="JDBC"/>
      <dataSourcetype="POOLED">
        <propertyname="driver"value="${driver}"/>
        <propertyname="url"value="${url}"/>
        <propertyname="username"value="${username}"/>
        <propertyname="password"value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapperresource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

当然,还有很多可以在XML 文件中进行配置,上面的示例指出的则是最关键的部分。要注意 XML 头部的声明,用来验证 XML 文档正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组 mapper 映射器(这些 mapper XML 文件包含了 SQL 代码和映射定义信息)。

不使用 XML 构建 SqlSessionFactory

如果你更愿意直接从 Java 程序而不是 XML 文件中创建 configuration,或者创建你自己的 configuration 构建器,MyBatis 也提供了完整的配置类,提供所有和 XML 文件相同功能的配置项。

DataSource dataSource =BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory =newJdbcTransactionFactory();
Environment environment =newEnvironment("development", transactionFactory, dataSource);
Configuration configuration =newConfiguration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory =newSqlSessionFactoryBuilder().build(configuration);

注意该例中,configuration 添加了一个映射器类(mapper class)。映射器类是 Java 类,它们包含 SQL 映射语句的注解从而避免了 XML 文件的依赖。不过,由于 Java 注解的一些限制加之某些 MyBatis 映射的复杂性,XML 映射对于大多数高级映射(比如:嵌套 Join 映射)来说仍然是必须的。有鉴于此,如果存在一个对等的 XML 配置文件的话,MyBatis 会自动查找并加载它(这种情况下, BlogMapper.xml 将会基于类路径和 BlogMapper.class 的类名被加载进来)。具体细节稍后讨论。

SqlSessionFactory 中获取 SqlSession

既然有了 SqlSessionFactory ,顾名思义,我们就可以从中获得 SqlSession 的实例了。SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:

SqlSession session = sqlSessionFactory.openSession();
try{
  Blog blog =(Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog",101);
}finally{
  session.close();
}

 六,创建Mybatis Demo

        可以参考这篇文章,https://blog.csdn.net/a909301740/article/details/78698682,感谢分享!


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值