1 框架概述

  • Mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注SQL语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
  • Mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中SQL的动态参数进行映射生成最终执行的SQL语句。
  • 最后mybatis框架执行SQL并将结果映射为java 对象并返回。采用ORM思想解决了实体和数据映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作

    2 配置文件

    2.1 映射配置文件(*Mapper.xml)

    插入文件

    • keyProperty 返回主键存储在pojo的那个属性里面
    • order selectKey的执行顺序,是相对于insert语句来说,由于mysql的自增原理执行完insert语句之后才能将主键生成,所以这里selectKey的执行顺序为after
    • resultType 返回的主键是什么类型
    • last_insert_id() 是mysql的函数,返回auto_increment自增列新记录id值
  • 如果主键是UUID,可以用数据库提供的uuid()函数来获取,此时的 order=”before” 因为是先生成的,resultType=”java.lang.String “ 。
  • 小结:

    • 插入语句使用的标签
    • 在映射文件中使用parameterType属性指定要插入的数据类型
    • SQL语句中使用#{属性名} 方式引用实体中的属性值
    • 插入操作使用的API是SQLSession.insert(“命名空间.ID”,实体对象)
    • 插入操作涉及数据库变化,所以要使用sqlSession对象显示的提交事务,即Sqlession.commit()
    • 对于主键返回可以在insert标签中,使用来返回主键

      #{} 和 ${}

  • {} 表示一个占位符,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换

    • {} 可以有效防止SQL注入。

    • {} 可以接收简单类型或pojo属性值。

    • 如果parameterType传输单个简单类型,#{}中的变量可以写入value或其他名称;如果parameterType传输的是实体类,则#{}中的变量只能写属性名。
  • ${}表示字符串拼接符号,通过{}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换

    • 可以接收简单类型值或pojo属性值
    • 如果parameterType传输单个简单的类型值,{}中只能是value;如果parameterType传输的是实体类,则${}中的变量只能写属性名

      里面的参数

  • namespace 表示命名空间,起到业务隔离作用,与SQL语句的ID组合起来使用成为SQL的唯一标识,也称为statementID

  • select *from orders as o inner join user as u where o.userId=u.id
  1. <a name="ZTvtL"></a>
  2. ## 2.2 核心配置文件(configuration里面的标签)
  3. - properties 属性
  4. ```java
  5. <properties resource="db.properties"/>
  6. 可以用来加载配置文件
  • setting 全局配置参数
  • typeAliases 类型别名
    • 该标签用于设置别名,设置后可以简化映射配置文件中的resultType、parameterType的类型配置
    • 为当前包下的所有类取别名
  • typeHandlers 类型处理器
    • 无论是Mybatis在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成java类型。
    • 可以重写类型处理器或者创建自己的类型处理器来处理不支持的或者非标准的类型
    • 实现org.apache.ibatis.type.TypeHander接口,或者继承一个便利的类org.apache.ibatis.type.BaseTypeHander,然后可以选择性地将它映射到一个JDBC类型
    • 例子:一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,取出来的时候转换成java的Date,即java的Date与数据库的bigint毫秒值之间的转换。
      • 1.定义转换类继承类BaseHander
      • 2.覆盖4个未来实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时mysql的字符串类型转换成java的Type类型的方法。
      • 3.在Mybatis核心配置文件中进行注册
  • objectFactory 对象工厂
  • plugins 插件
  • environments 环境集合属性对象(工作中有生产环境和上线环境)
    • environment 环境子属性对象
      • transactionManager 事务管理
        • JDBC:这个配置就是直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务的作用域。
        • MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如JEE应用服务器的上下文)。默认使用情况下他会关闭连接,然而一些容器并不希望这样,因此需要将closeConnection属性设置为false来阻止它默认的关闭行为。
      • DataSource 数据源
        • UNPOOLED 这个数据源的实现只是每次被请求时打开和关闭连接
        • POOLED 这种数据源的实现利用“池”的概念将JDBC连接对象组织起来
        • JDNI 这个数据源的实现是为了能在如EJB或应用服务器这类容器中使用,容器可以集中或者在外部配置数据源,然后放置一个JDNI上下文的引用
  • mappers 映射器

    • 使用相对于类路径的资源,就是resources文件夹,
    • 使用mapper接口类路径
      • 此方法要求mapper接口名称和mapper映射文件名称相同,切放在同一个目录
    • 注册指定包下面的所有mapper接口
      • 此方法要求mapper接口名称和mapper映射文件名称相同,切放在同一个目录中

        3 核心API

  • SqlSessionFactoryBuilder()

    • 通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象
    • 其中Resources工具类,这个类在org.apache.ibatis.io包中。Resources类帮助你从类路径下、文件系统或一个WebURL中加载资源文件
  • SQLSessionFactory
    • 是一个接口,其中接口定义了openSession的不同加载方法;SQLSessionFactory是线程安全的,而且SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SQLSessionFactory。
    • openSession() 可以有参数,若为 true 就是自动提交事务
  • SqlSession

    • 是一个面向用户(程序员)的接口,sqlSession中定义了数据库操作方法。
    • 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的线程范围是请求或方法范围
    • 绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中
    • 打开一个SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到finally块中以确保每次都能执行关闭。

      4 代理开发方式

  • 采用Mybatis的代理开发方式实现DAO层的开发,这种方式是进入企业后的主流方式,也叫mapper代理开发

  • Mapper接口开发方法只要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法
  • Mapper接口开发需要遵循以下的规范

    • 接口与SQL映射文件的包名,类名相同
    • Sql映射文件的namespace为接口的全限定名称(包名.类名)
    • 接口方法名与statement的id值相同;接口方法参数类型与statment中parameterType值相同
    • 接口方法返回类型与statment中resultType值相同

      5 动态SQL

      <foreach collection="list" open="id in (" close=")" item="id" separator=",">
      #{id}
      </foreach>
      
      <select id="findByIdS" parameterType="Integer" resultType="User">
         select * from `user`
         <where>
             <foreach collection="list" open="id in (" close=")" item="id" separator=",">
                 #{id}
             </foreach>
         </where>
      </select>
      
  • collection 代表要遍历的集合元素,注意编写时不要写#{}

  • open 代表语句开始部分
  • close 代表结束部分
  • item 代表遍历集合的每一个元素
  • separator 代表分隔符,每次一循环都要拼接该分割符
    <!--    如果没有参数 where会自动省略-->
      <select id="findByCondition" resultType="User" parameterType="User">
          select * from `user`
          <where> 
              <if test="username != null">
                  username = #{username}
              </if>
              <if test="sex != null">
                  and sex = #{sex}
              </if>
          </where>
      </select>
    
    ```java / SQL片段抽取 抽取重复SQL /
select * from user
<select id="findByName" resultType="User" parameterType="String">
    <include refid="selectUser"></include> where `username` like concat("%",#{name},"%")
</select>

<select id="findAll" resultType="User">
    <include refid="selectUser"></include>
</select>

```

6 mybatis延迟加载策略

  • 延迟加载(lazy load),延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。
  • 前面实现多表操作使用的是resultMap来实现一对一,一对多,多对多关系的操作。主要是通过association、collection实现一对一及一对多的映射。association、collection具备延迟加载功能。
  • 延迟加载(按需加载|懒加载):当真正需要数据的时候,才真正的执行加载操作。

7 注解开发

7.1 常用注解

  • @insert 类似于标签,用于声明插入操作
  • @Update 类似于标签,用于声明更新操作
  • @Delete 类似于标签,用于声明删除操作
  • @Select 类似于