回顾MyBatis

3.1JDBC问题总结


       1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。

设想:使用数据库连接池管理数据库连接。

      2、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。

设想:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。

      3、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。

设想:将sql语句及占位符号和参数全部配置在xml中。

      4、从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。

设想:将查询的结果集,自动映射成java对象。


3.2Mybatis框架


3.2.1简介


       MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github。

       MyBatis 是支持普通 SQL查询存储过程高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

  • MyBatis让程序将主要精力放在sql上,通过MyBatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
  • MyBatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)


3.2.2功能架构


Mybatis的功能架构分为三层:


       1) API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

       2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

       3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

                     回顾MyBatis_第1张图片


3.3流程


3.3.1创建SqlSession的流程

 

                       回顾MyBatis_第2张图片

                       回顾MyBatis_第3张图片


3.3.2开发流程


创建表User添加配置文件(可自定义命名)SqlMapConfig.xml定义与表对应的实体User定义操作表的sql映射文件UserMapper.xml在SqlMapConfig.xml注册UserMapper.xml测试代码(User user = session.selectOne(statement, 1);)

注意:MyBatis是一个不完全 的ORM框架,没有实体映射到表的功能,所以都是自己创建表。


3.3.3原始dao层开发


        原始dao 的方法

        需要程序员编写dao接口和实现类

        需要在dao实现类中注入一个SqlSessionFactory工厂。

public class UserDaoImpl implements UserDao {

 

// 需要向dao实现类中注入SqlSessionFactory

// 这里通过构造方法注入

private SqlSessionFactory sqlSessionFactory;

 

public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {

this.sqlSessionFactory = sqlSessionFactory;

}

 

@Override

public User findUserById(int id) throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

 

User user = sqlSession.selectOne("test.findUserById", id);

 

// 释放资源

sqlSession.close();

 

return user;

}

 

3.3.4mapper代理开发(推荐使用)


       只需要程序员编写mapper接口(就是dao接口)

       程序员在编写mapper.xml(映射文件)和mapper.java需要遵循一个开发规范:

             1、mapper.xml中namespace就是mapper.java的类全路径。

             2、mapper.xml中statement的id和mapper.java中方法名一致。

             3、mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入 参数类型一致。

             4、mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致。

      SqlMapConfig.xml配置文件:可以配置properties属性、别名、mapper加载。。。

          回顾MyBatis_第4张图片


3.3.5输入映射


       parameterType:指定输入参数类型可以简单类型、pojo、hashmap。。

       对于综合查询,建议parameterType使用包装的pojo,有利于系统扩展。


3.3.6输出映射


resultType:

       查询到的列名和resultType指定的pojo的属性名一致,才能映射成功。

reusltMap:

        可以通过resultMap 完成一些高级映射。

        如果查询到的列名和映射的pojo的属性名不一致时,通过resultMap设置列名和属性名之间的对应关系(映射关系)。可以完成映射。

高级映射:

       将关联查询的列映射到一个pojo属性中。(一对一)

       将关联查询的列映射到一个List中。(一对多)


3.4核心


3.4.1核心配置xml








    

         

             

             

             

                

                

                

                 

            

         

     

    

    

         

         

     

    




3.5接口介绍


3.5.1 SqlSessionFactoryBuilder


       每一个MyBatis的应用程序的入口是SqlSessionFactoryBuilder,它的作用是通过XML配置文件创建Configuration对象(当然也可以在程序中自行创建),然后通过build方法创建SqlSessionFactory对象。


3.5.2 SqlSessionFactory


       SqlSessionFactory对象由SqlSessionFactoryBuilder创建。它的主要功能是创建SqlSession对象,和SqlSessionFactoryBuilder对象一样,没有必要每次访问Mybatis就创建一次SqlSessionFactory,通常的做法是创建一个全局的对象就可以了。


3.5.3 SqlSession


        SqlSession对象的主要功能是完成一次数据库的访问和结果的映射,它类似于数据库的session概念,由于不是线程安全的,所以SqlSession对象的作用域需限制方法内。

SqlSession session= sqlSessionFactory.openSession();  

UserDao userDao = session.getMapper(UserDao.class);  

UserDao user = new UserDao();  

user.setUsername("iMybatis");  

List users = userDao.queryUsers(user);  

 

3.5.4 Executor


       Executor对象在创建Configuration对象的时候创建,并且缓存在Configuration对象里。Executor对象的主要功能是调用StatementHandler访问数据库,并将查询结果存入缓存中(如果配置了缓存的话)。


3.5.5 StatementHandler


       StatementHandler是真正访问数据库的地方,并调用ResultSetHandler处理查询结果。


3.5.6 ResultSetHandler


       处理查询结果。

 

3.6缓存


       mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

       mybaits提供一级缓存,和二级缓存。

       回顾MyBatis_第5张图片

       一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

       二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。


为什么要用缓存?

       如果缓存中有数据就不用从数据库中获取,大大提高系统性能。


3.6.1一级缓存

               回顾MyBatis_第6张图片

第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

       mybatis默认支持一级缓存,不需要在配置文件去配置。

 

3.6.2二级缓存


1.原理

                  回顾MyBatis_第7张图片

首先开启mybatis的二级缓存。

sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。


2.配置

        mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

  • 在核心配置文件SqlMapConfig.xml中加入:

        

  • 在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap):

       


3.二级应用场景

       对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。


4.二级缓存的局限性

        mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。


3.7动态SQL


        MyBatis核心 对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、

你可能感兴趣的:(Java)