Mybatis笔记

一、 mybatis框架

    1.mybatis是什么?

mybatis是一个持久层框架,mybatis是一个不完全的ORM框架。sql语句需要程序员自己去编写,但是mybatis也有映射(输入参数映射、输出结果映射)。mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射).Mybatis 只是对于 jdbc 的封装。

    2.mybatis框架

    3.mybatis框架执行过程:

(1)配置mybatis的配置文件,SqlMapConfig.xml(名称不固定)
(2)通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂
         SqlSessionFactory在实际使用时按单例方式。
(3)通过SqlSessionFactory创建SqlSession
         SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内。
(4)调用sqlSession的方法去操作数据。
         如果需要提交事务,需要执行SqlSession的commit()方法。
(5)释放资源,关闭SqlSession
 

二、Dao开发方法

    2.1 原始Dao开发方法

(1)映射文件
(2)Dao接口
(3)Dao接口实现类
Public class UserDaoImpl implements UserDao {
 
    //注入SqlSessionFactory
    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
    this.setSqlSessionFactory(sqlSessionFactory);
    }
 
    private SqlSessionFactory sqlSessionFactory;
    @Override
    public User getUserById(int id) throws Exception {
        SqlSession session = sqlSessionFactory.openSession();
        User user = null;
        try {
            //通过sqlsession调用selectOne方法获取一条结果集
            //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
            user = session.selectOne("test.findUserById", 1);
            System.out.println(user);
            } finally{
                session.close();
            }
        return user;
       }
 
    @Override
    Public void insertUser(User user) throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            sqlSession.insert("insertUser", user);
            sqlSession.commit();
        } finally{
            session.close();
        }
    }
}
(4)问题
  原始Dao开发中存在以下问题:
******Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
******调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护
 

    2.2 Mapper接口开发方法(Mapper动态代理方式)

(1)实现原理
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
【1】 Mapper.xml文件中的namespace与mapper接口的类路径相同。
【2】 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
【3】 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
【4】Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
(2)Mapper.xml映射文件
(3)接口文件
(4)加载Mapper.xml文件
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
(5)测试
InputStream is = Resources.getResourceAsStream("mybatis/SqlMapConfig.xml");
//通过配置文件SqlMapConfig.xml,创建SqlSessionFactory对象,然后产生SqlSession,执行SQL语句
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取代理对象
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.selectById(1);
System.out.println(user);
//关闭session
sqlSession.close();

三、XML配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
<configuration>
 
<!-- 加载类路径下的属性文件 -->
<properties resource="jdbc.properties"/>
 
<!-- settings -->
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载(即按需加载) -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
<setting name="cacheEnabled" value="true"/>
</settings>
 
<!-- 设置类型别名 -->
<typeAliases>
<typeAlias type="ljh.entity.User" alias="user"/>
</typeAliases>
 
<!-- spring整合后 environments配置将废除-->
<!-- 设置一个默认的连接环境信息 -->
<environments default="mysql">
<!-- 连接环境信息,取一个任意唯一的名字 -->
<environment id="mysql">
<!-- mybatis使用jdbc事务管理方式 -->
<transactionManager type="JDBC"/>
<!-- mybatis使用连接池方式来获取连接 -->
<dataSource type="pooled">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
 
<!-- 加载映射文件-->
<mappers>
<mapper resource="mybatis/mapper/UserMapper.xml"/>
</mappers>
</configuration>
SqlMapConfig.xmlmybatis核心配置文件,上边文件的配置内容为数据源、事务管理。

3.1配置内容

SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)

3.2配置详讲

(1)类型别名(typeAliases)
类型别名是为 Java 类型设置一个短的名字。 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
(2)环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
(3)事务管理器(transactionManager)
  (4)数据源(dataSource)
  (5)映射器(mappers)
告诉 MyBatis 到哪里去找映射文件
*******<mapper resource=" " />使用相对于类路径的资源
*******<mapper url=" " />使用完全限定路径
*******<mapper class=" " />使用mapper接口类路径 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
*******<package name=""/>注册指定包下的所有mapper接口  注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
 

四、XML映射文件

1、namespace等于mapper接口地址

2、输入映射(输入类型)

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo,pojo的包装类型

3、输出映射(输出类型)

(1)resultType
******使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
******如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
******只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。不一致的属性值为null。
******输出单个pojo对象,方法返回值是单个对象类型
******输出pojo对象list,方法返回值是List<Pojo>
******如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身
(2)resultMap
mybatis中使用resultMap完成高级输出结果映射。一致
4、动态sql
(1)If
    <select id="findUserList" parameterType="user" resultType="user">
       select * from user
       where 1=1
       <if test="id!=null and id!=''">
       and id=#{id}
       </if>
       <if test="username!=null and username!=''">
       and username like '%${username}%'
       </if>
    </select>
 
注意要做不等于空和空字符串校验。
(2)where
<select id="findUserList" parameterType="user" resultType="user">
       select * from user
       <where>
       <if test="id!=null and id!=''">
       and id=#{id}
       </if>
       <if test="username!=null and username!=''">
       and username like '%${username}%'
       </if>
       </where>
 </select>
<where />可以自动处理第一个and
(3) foreach
向sql传递数组或List,mybatis使用foreach解析
* 需求:传入多个id查询用户信息,用下边两个sql实现:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%'  id IN (10,89,16)
WHERE id=1 OR id=10 OR id=16
在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。

(4) sql片段

需求:将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。方便程序员进行开发。

定义sql片段

引用sql片段

mapper.xml中定义的statement中引用sql片段:

五、延迟加载

需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载。【用的时候加载不用的时候不加载】
mybatis核心配置文件中配置:
lazyLoadingEnabledaggressiveLazyLoading
设置项
描述
允许值
默认值
lazyLoadingEnabled
全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。
true | false
false
aggressiveLazyLoading
当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。
true | false
true
mybatis核心配置文件中配置
<settings>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="aggressiveLazyLoading" value="false"/>
</settings>
 

六、Mybatis连接池和事务

1、连接池

(1)mybatis连接池分类
可以看出 Mybatis 将它自己的数据源分为三类:
 UNPOOLED 不使用连接池的数据源
 POOLED 使用连接池的数据源(最常用)
 JNDI 使用 JNDI 实现的数据源
(2)Mybatis中数据源的配置
MyBatis 在初始化时,解析此文件,根据的 type 属性来创建相应类型的的数据源DataSource,即:type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
(3)Mybatis 中连接的获取过程分析
当我们需要创建 SqlSession 对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource 对象
来创建 java.sql.Connection 对象。也就是说,java.sql.Connection 对象的创建一直延迟到执行 SQL 语句
的时候。
数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再立即将数据库连接归还到连接池中。

2、Mybatis的事务控制

(1)JDBC中事务的控制在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。
Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC
的 setAutoCommit()方法来设置事务提交方式的
SqlSession sqlSession = sqlSessionFactory.openSession(true);//手动将他的事务提交方式改为自动提交
掌握 Mybatis连接池技术、事务、复杂参数的传入、复杂结果集的封装,多表的关联查询。

七、查询缓存

 1.SqlSessionFactoryBuilder、SqlSessionFacoty、SqlSession

  sqlSessionFactory是mybatis中的一个中要的对象,通俗讲它是用来创建sqlSession对象的,而sqlSession用来操作数据库的。
(1)SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
(2)SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
(3)SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。
执行过程如下:
1. 加载数据源等配置信息
Environment environment = configuration.getEnvironment();
2. 创建数据库链接
3. 创建事务对象
4. 创建Executor,SqlSession所有操作都是通过Executor完成,mybatis源码如下:
5. SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor
结论:
         每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
         打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:
         SqlSession session = sqlSessionFactory.openSession();
         try {
                 // do work
         } finally {
               session.close();
         }

2.Mybatis缓存介绍

(1)mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits提供一级缓存,和二级缓存。
        如下图,是mybatis一级缓存和二级缓存的区别图解:
Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。Mybatis默认开启一级缓存。
 
 
Mybatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
 

3.一级缓存

 
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

4.二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。
在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
    
刷新缓存(就是清空缓存)
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。
 

八、 mybatis逆向

1、什么是逆向工程

 
mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml、po..)
 
企业实际开发中,常用的逆向工程方式:
由于数据库的表生成java代码。

2、使用方法(会用)

运行逆向工程, 生成代码配置文件,执行生成程序, 使用生成的代码
 
 
 
 
 
 

 

 
 
posted on 2019-08-20 20:11  天高任鸟飞,海阔任鱼游  阅读(140)  评论(0编辑  收藏  举报