Hibernate缺点:java
一、运行效率低,内存占用比较严重sql
二、针对单一对象的增删改查,适合Hibernate,而Hibernate在批量操做时处于弱势数据库
三、虽然Hibernate引入一二级缓存、lazyload、查询缓存等更多优化空间(对于那些改动 不大且常用的数据,可将他们放入缓存中),但Hibernate对于持久层封装过于完 整,致使开发人员没法对sql进行优化,不适用于大型项目设计模式
mybatis优势:缓存
一、代码量大大减小,开发效率高安全
二、 MyBatis至关灵活,SQL写在XML里,从程序代码中完全分离,下降耦合度,便于统 一管理和优化,并可重用bash
三、运行效率高session
下面是mybatis的一个原理图,看懂这个图对理解mybatis工做原理很重要:mybatis
上面的原理图看的不是很清晰,下面再详细介绍一下mybatis的主要成员:app
一、Configuration
MyBatis全部的配置信息都保存在Configuration对象之中,配置文件的大部分配置都会存储到该类中
二、SqlSession
做为MyBatis工做的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能
三、Executor
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler 封装了JDBC Statement操做,负责对JDBC statement 的操做,如设置参数等
四、ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所对应的数据类型
五、ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
六、TypeHandler
负责java数据类型和jdbc数据类型(也能够说是数据表列类型)之间的映射和转换
七、MappedStatement
MappedStatement维护一条<select|update|delete|insert>节点的封装
八、SqlSource
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
九、BoundSql
表示动态生成的SQL语句以及相应的参数信息
下面介绍一下mybatis的工做流程:
首先,mybatis的增删改查这些数据库操做都是基于sqlsession类的,SqlSession又是由SqlSessionFactory类建立出来的(这里采用了java设计模式中的工厂模式),而SqlSessionFactory是由SqlSessionFactoryBuilder建立的,SqlSessionFactoryBuilder要想建立SqlSessionFactory,必需要有原料(即mybatis配置文件),下面是建立SqlSession的代码:
//加载classpath路径下的mybatis配置文件InputStream in=Resources.getResourceAsStream("mybatis-config.xml");//根据加载配置文件产生的输入流,来建立一个SqlSessionFactorySqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);//根据SqlSessionFactory建立SqlSessionSqlSession session = sessionFactory.openSession();复制代码
下面介绍这几个重要对象的做用域和生命周期
一、SqlSessionFactoryBuilder
这个类能够被实例化、使用和丢弃,一旦建立了 SqlSessionFactory,就再也不须要它了。所以 SqlSessionFactoryBuilder 实例的最佳做用域是方法做用域(也就是局部方法变量)。你能够重用 SqlSessionFactoryBuilder 来建立多个 SqlSessionFactory 实例,可是最好仍是不要让其一直存在以保证全部的 XML 解析资源开放给更重要的事情。
二、SqlSessionFactory
SqlSessionFactory 一旦被建立就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复建立屡次。所以 SqlSessionFactory 的最佳做用域是应用做用域。有不少方法能够作到,最简单的就是使用单例模式或者静态单例模式
三、SqlSession
每一个线程都应该有它本身的 SqlSession 实例。SqlSession 的实例不是线程安全的,所以是不能被共享的,因此它的最佳的做用域是请求或方法做用域。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。sqlSession在每次用完以后必须关闭它
一、一级缓存
MyBatis一级缓存是基于sqlSession的,sqlSession对象有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象没法访问。一级缓存默认是开启的,且没法关闭。增删改操做会清空当前sqlSession里的缓存
二、二级缓存
MyBatis二级缓存是mapper级别的缓存,同一个namespace共用这一个缓存,因此对SqlSession是共享的,二级缓存是默认关闭的。
如何配置二级缓存?只须要在sql映射文件中添加<cache/>便可
测试代码:
/* * 注意:被缓存的数据要实现序列化接口(在这里将Book.java实现序列化接口),不然会出现异常 * 另外,当某一个sqlSession修改了共享的缓存数据以后,二级缓存也会清空 */SqlSession session_1 = MyBatisUtil.getSession();BookDao mapper_1 = session_1.getMapper(BookDao.class);mapper_1.listBook();//注意,必须提交才能将数据放进二级缓存session_1.commit(); SqlSession session_2 = MyBatisUtil.getSession();BookDao mapper_2 = session_2.getMapper(BookDao.class);mapper_2.listBook();复制代码
这里只是为了测试二级缓存的原理,因此MyBatisUtil类如何获取SqlSession的代码就没有粘贴进来了。
运行上面的代码,经过log4j打印出来的日志能够看到,,明明运行了两次listBook方法,但最终查询语句(select * from book)只出现一次,此次由于第二次查询命中了缓存,就不须要再查数据库了。