Mybatis是一个基于Java的持久层框架。
MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis避免了几乎所有的JDBC代码和手工设置参数以及抽取结果集。MyBatis用简单的XML或注解来配置和映射基本体,将接口和Java的POJOs映射成数据库中的记录。
从JDBC到Mybatis
jdbc示例
原始的JDBC操作数据库频繁开启和关闭数据库连接造成资源浪费以及大量的样板代码等,Mybatis是对JDBC进行封装的一个持久层框架,可以为应用开发简化持久层开发。
一、对于JDBC哪些步骤可以进一步封装
1、连接获取和释放
问题:数据库连接频繁的开启和关闭本身就造成了资源的浪费,影响系统的性能。
解决:数据库连接的获取和关闭可以使用数据库连接池来解决资源浪费的问题。通过连接池就可以反复利用已经建立的连接去访问数据库了。减少连接的开启和关闭的时间。
一般常用的有JDBC连接池或JNDI数据库连接池。
2、SQL统一存取
问题:使用JDBC进行操作数据库时,SQL语句基本都散落在各个JAVA类中,这样有三个不足之处:
(1)、可读性差,不利于维护以及做性能调优
(2)、改动JAVA代码需要重新编译、打包部署
(3)、不利于取出SQL在数据库客户端执行
解决:可以将这些SQL语句统一集中放到配置文件或者数据库中(以key-value的格式存放)。然后通过SQL语句的key值去获取对应的SQL语句。
3、更灵活的传入参数映射和动态SQL
问题:通常通过在SQL语句中设置点位符来达到使用传入参数的目的,这种方式本身就有一定局限性,它是按照一定顺序传入参数的,要与占位符一一匹配。但是,如果我们传入的参数是不确定的(比如列表查询,根据用户填写的查询条件不同,传入查询的参数也不同的),那么我们就得在后台代码中自己根据请求的传入参数去拼凑相应的SQL语句,这样的话避免不了在Java代码里写SQL语句的命运。
解决:通过引入<if>这样的标签,需要专门的sql解析器解析这样的判断结果是否为true来输出标签里面的sql片断。并通过不标识符区分开点位符变量和非点位符变量。使用#变量名,#表示点位符变量,使用$变量名$表示非点位符变量。
4、结果映射和结果缓存
问题:执行sql语句获取执行结果,返回ResultSet结果集后,需要将结果集数据取出来,释放资源后便取不到结果信息。
解决:对于结果可能需要做的处理有,将结果转换成一个javabean对象返回、一个map返回、一个list返回等,需要告诉sql处理器两点(1)、需要返回什么类型的对象(2)、需要返回的对象的数据结构怎么跟执行的结果映射。再考虑对sql执行结果的缓存来提升性能。缓存以key-value格式保存,sql语句和传入参数部分合起来可以作为数据缓存的key值。
5、解决重复SQL语句问题
问题:由于所有sql语句都放到配置文件中,这个时候遇到一个sql重复的问题,几个功能的sql语句其实都差不多,有些可能是select后面那段不同、有些可能是where语句不同。有时候结构改了,那么我们需要改多个地方,不利于维护。
解决:将重复的代码抽离出来成为独立的一个类,然后在各个需要使用的地方进行引用。对于sql重复问题,可以采用,通过将sql片段模块化,将重复的sql片段独立成一个sql块,然后在各个sql语句中引用重复的sql块。
优化总结:
我们总结一下上面对JDBC的优化和封装:
(1) 使用数据库连接池对连接进行管理
(2) SQL语句统一存放到配置文件
(3) SQL语句变量和传入参数的映射以及动态SQL
(4) 动态SQL语句的处理
(5) 对数据库操作结果的映射和结果缓存
(6) SQL语句的重复
mybaits的部体流程
1、加载配置并初始化
触发条件:加载配置文件
配置文件来源于两个地方,一处是配置文件,一处是java代码的注解,将sql的配置信息加载成为一个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
2、接收调用请求
触发条件:调用Mybatis提供的API
传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。
3、处理操作请求
触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象
处理过程:(A)根据SQL的ID查找对应的MappedStatement对象
(B)根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
(C)获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(D)根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(E)释放连接资源。
4、返回处理结果
将最终的处理结果返回。
mybatis功能架构设计
功能架构分为三层:
(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
mybatis具体执行流程图
SqlSessionFactoryBuilder
每一个mybatis的应用程序的入口是SqlSessionFactoryBuilder,它的作用是通过XML配置文件创建Configuration对象,然后通过build方法创建SqlSessionFactory对象。一般使用全局。
private static SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
private static SqlSessionFactory sqlSessionFactory;
private static void init() throws IOException {
String resource = "mybatis-config.xml";
Reader reader = Resources.getResourceAsReader(resource);
sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(reader);
}
SqlSessionFactory
它的主要功能是创建SqlSession对象,一般使用全局。SqlSessionFactory对象一个必要的属性是Configuration对象,它是保存Mybatis全局配置的一个配置对象,通常由SqlSessionBuilder从XML配置文件创建。
SqlSession
SqlSession对象的主要功能是完成一次数据库的访问和结果的映射,它类似于数据的session概念,由于不是线程安全,所以SqlSession对象的作用域需要限制方法内。SqlSession的默认实现类是DefaultSqlSession,它有两个必须配置属性:Configuration和Executor。SqlSession对数据库的操作都是通过Executor来完成的。
SqlSession有一个重要的方法getMapper,顾名思义,这个方式是用来获取Mapper对象的。什么是Mapper对象?根据Mybatis的官方手册,应用程序除了要初始并启动Mybatis之外,还需要定义一些接口,接口里定义访问数据库的方法,存放接口的包路径下需要放置同名的XML配置文件。SqlSession的getMapper方法是联系应用程序和Mybatis纽带,应用程序访问getMapper时,Mybatis会根据传入的接口类型和对应的XML配置文件生成一个代理对象,这个代理对象就叫Mapper对象。应用程序获得Mapper对象后,就应该通过这个Mapper对象来访问Mybatis的SqlSession对象,这样就达到里插入到Mybatis流程的目的。示例代码如下:
SqlSession session= sqlSessionFactory.openSession();
UserDao userDao = session.getMapper(UserDao.class);
UserDto user = new UserDto();
user.setUsername("iMybatis");
List<UserDto> users = userDao.queryUsers(user);
Executor
Executor对象在创建Configuration对象的时候创建,并且缓存在Configuration对象里。Executor对象的主要功能是调用StatementHandler访问数据库,并将查询结果存入缓存中。
StatementHandler
StatementHandler是真正访问数据库的地方,并调用ResultSetHandler处理查询结果。
ResultSetHandler
处理查询结果。
MyBatis的优缺点
优点:
1、简单易学
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳
总结
mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。
mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql语句。
Mybaits有待改进之处
问题描述:
Mybaits所有的数据库操作都是基于SQL语句,导致什么样的数据库操作都要写SQL语句。一个应用系统要写的SQL语句实在太多了