最近读了《深入浅出Mybatis》,感觉非常适合新手入手,或者刚工作一两年,接触到Mybatis,里面介绍了很多小技巧,便于在开发过程中使用,以下是我的一些读后感。
1.什么是ORM模型
ORM模型就是数据库的表和简单Java对象(Plian Ordinary Java Object,简称POJO)的映射关系模型,它主要解决数据库数据和POJO对象的相互映射。
2. 说说Hibernate
Hibernate是建立在若干POJO通过XML映射文件(或注解)提供的规则映射到数据库表上的。换句话说,我们可以通过POJO直接操作数据库的数据,它提供的是一种全表映射的模型。
Hibernate的缺点?
1)全表映射带来的不便,比如更新时需要发送所有的字段
2)无法根据不同的条件组装不同的SQL,虽然可以通过HQL拼接SQL
3)对多表关联和复杂的SQL查询支持较差
4)不能有效的支持存储过程
5)不支持表名称动态
6)表字段动态或者不固定,则无法实现
7)HQL的性能较差,在大型互联网中需要优化SQL
3. Mybatis
Mybatis的前身是Apache的一个开源项目iBatis,是一个基于Java的持久层框架。Mybatis所需要提供的映射文件包含以下三个部分:
1)SQL
2) 映射规则
3) POJO
Mybatis几乎开源代替JDBC,拥有动态列、动态表名、存储过程等都支持,同时提供了简易的缓存、日志、级联。但是他的缺点是需要你提供映射规则和SQL,相对于Hibernate的工作量大一些。
Mybatis的基本构成及生命周期
1) SqlSessionFactoryBuilder(构造器),它会根据配置信息或者代码来生成SqlSessionFactory(工厂接口)。
SqlSessionFactoryBuilder是利用XML或者Java编码获得资源来构建的SqlSessionFactory的,通过它可以构建多个SqlSessionFactory。它的作用就是一个构建器,一旦我们构建了SqlSessionFactory,他的作用就已经完结,我们应该毫不犹豫的将其收回,生命周期只存在方法的局部,他的作用就是生产SqlSessionFactory对象。
2) SqlSessionFactory:依靠工厂来生成SqlSession(会话)。
SqlSessionFactory的作用是创建SqlSession,而SqlSession就是一个会话,相当于JDBC中的Connection对象,每次应用程序访问数据库,我们就要通过SqlSessionFactory创建的SqlSession,所以SqlSessionFactory应该在Mybatis应用的整个生命周期中。为了减少数据库的连接,我们采用SqlSessionFactory是单例。
3) SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取Mapper的接口。
SqlSession是一个会话,相当于JDBC中的一个Connection对象,他的生命周期应该是在请求数据库处理事务的过程中。它是一个线程不安全的对象,每次创建的SqlSession都必须及时关闭它。
4) SQL Mapper:它是Mybatis新设计的组件,它是由一个Java接口和XML文件(或者注解)构成的,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。
Mapper是一个接口,而没有任何实现类,他的作用就是发生SQL,然后返回我们需要的结果,或者执行SQL从而修改数据库的数据,因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西。
4. Mybatis bind元素
bind元素的作用是通过OGNL表打死去自定义一个上下文变量,这样更方便我们使用,在我们进行模糊查询的时候,如果是Mysql数据库,我们常常用到的是一个concat 用 “%” 和参数相连接,然而在Oracle数据库则是用连接符“||”,这样SQL就需要提供两种方式去实现。
<select id="xxx" resultMap = "xxx">
select * from User where name like concat ('%', #{name}, '%')
</select>
<select id="xxx" resultMap = "xxx">
<bind name="bind_name" value = "'%' + name + '%'"/>
select * from User where name like #{bind_name}
</select>
5. 构建SqlSessionFactory过程
第一步:通过org.apache.ibatis.builder.xml.XMLConfigBuilder解析配置的XML文件,读出配置参数,并将读取的数据存入这个org.apache.ibatis.session.Configuration类中,注意:Mybatis几乎所有的配置都是存在这里的。
第二步:使用Configuration对象去创建SqlSessionFactory.SqlSessionFactory是一个接口,Mybatis默认提供了一个DefaultSqlSessionFactory实现类
6. 构建Configuration
1) 读取配置文件,包括基础配置的XML文件和映射器的XML文件
2) 初始化基础配置,比如Mybatis的别名等,一下重要的类对象,比如,插件、映射器、ObjectFactroy和typeHandler对象
3) 提供单例,为后续构建SessionFactory服务提供配置的参数
4) 执行一些重要的对象方法,初始化配置信息
当修改sql语句的时候,需要重新加载mapper文件,这个时候可以通过Configuration类来帮助我们实现热加载,而不需要重启服务器。
7. SqlSession的四大对象
1、Executor 执行器:由它来调度StatementHandler、ParamenterHandler、ResultHandler等来执行对应的SQL
2、StatementHandler(数据库会话器)的作用是使用数据库Statement(PreparedStatement)执行操作,它是四大对象的核心,起到承上启下的作用。
3、ParamenterHandler(参数处理器)用于SQL对参数的处理。
4、ResultHandler(结果处理器)是进行最后数据集的封装返回处理的
8. 一条查询SQL的执行过程
Executor会先调用StatementHandler的prepare()方法预编译SQL语句,同时设置一些基本运行的参数。然后调用parameterize()方法启用ParamenterHandler设置参数,完成预编译。跟着就是执行查询,最后如果有结果集,就调用ResultHandler封装结果集返回给调用者。
9. SqlSession运行总结
SqlSession是通过Executor创建StatementHandler来运行的,而StatementHandler要经过下面三步:
1)prepared 预编译SQL
2)parameterize 设置参数
3)query/update 执行SQL
其中 parameterize 是调用 PreparedStatement的方法去设置的,而参数是跟根据类型处理器typeHandler 去处理的。query/update 方法是通过resultHandler进行处理结果的封装,如果是update的语句,它就是返回整数,否则它就是通过typeHandler处理结果类型,然后用ObjectFactory提供的规则组装对象,返回给调用者。
10. 事务隔离级别
1)脏读 :一个事务能够读取另一个事务未提交的数据。
2)读写提交:就是一个事务要等另一个事务提交后才能读取数据。
3)可重复读:就是在开始读取数据(事务开启)时,不再允许修改操作
4)序列化:是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
11. spring事务传播特性:
事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:
propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。
12. 分页插件
自定义先查询总量,然后再limit查询
推荐第三方插件:Pagehelper(com.github.pagehelper)