浅谈Mybatis

what is mybatis?

  mybatis的前身是ibatis, 本是apache的一个开源项目,2010年这个项目由apache软件基金会迁移到了google code , 并且改名为mybatis.

  mybatis是支持普通sql查询、存储过程和高级映射的持久层框架,半自动ORM框架。

  mybatis消除了几乎所有的JDBC代码和参数的手工设置,以及结果集的检索。

可以使用简单的XML或注解用于配置和原始映射,将接口和java的POJOS映射成数据库的记录。

Mybatis官网:http://www.mybatis.org/mybatis-3

Github: https://github.com/mybatis/mybatis-3

 

 

 

 

JDBC的操作

  

 

 

 

   

Mybatis对应的操作

  

 

 

 

一、获取数据源

SqlSessionFactoryBUilder.java ----> build(InputStream inputStream) ----> build(InputStream inputStream, String environment, Properties properties)

XMLConfigBuilder.java ----> parse() ----> parseConfiguration(XNode root) ----> environmentsElement(XNode context)                                              

 

Mybatis获取 DataSource 流程图:

 

 

 

二、获取执行语句

DefaultSqlSessionFactory.java ---> openSession()

DefaultSqlSession.java  ----> getMapper(Class<T> type)

Configuration.java  ------> getMapper(Class<T> type, SqlSession sqlSession)

MapperRegiststry.java --->  getMapper(Class<T> type, SqlSession sqlSession)

MapperProxyFactory.java ----> newInstance(SqlSession sqlSession)

MapperProxy.java ----> invoke(Object proxy, Method method, Object[] args)

MapperMethod.java ----> execute(SqlSession sqlSession, Object[] args)

 

Mybatis获取 Mapper 流程图:  

 

 

   

三、操作,执行Sql脚本

DefaultSqlSessionFactory.java ----> openSession() ----> openSessionFromDataSource(Executor, TransactionIsolationLevel, boolean autoCommit)

Configuration.java ----> newExecutor(Transaction, ExecutorType) 

DefaultSqlSession ---> selectOne() ---> selectList(statement, parameter) 

                                     MappedStatement.java ---> getBoundSql(parameterObject)

CachingExecutor.java ---> query() : ms.getBoundSql() ----> BoundSql.java (获取查询的sql)

                                 createCacheKey(构建一级缓存)  ----> CacheKey.java

                ---> delegate.query()

BaseExecutor.java ----> query() --判断缓存key是否存在 ; 

                  不存在 -----> queryFromDataBase() -- doQuery()

SimpleExecutor.java ----> doQuery(MappedStatement, parameter, RowBounds, ResultHandler, BoundSql)

              拿到StatementHandler.java ----> query() -----> SimpleStatementHandler.java ---> query() : 执行sql脚本

 

 

  

 

 Mybatis的执行器类图关系:

 

 

  

完整链路图

  

 

一、根据配置文件创建SqlSessionFactory

把配置文件中的信息解析并保存在Configuration对象中,返回包含configuration的DefaultSqlSessionFactory对象

SqlSessionFactoryBuilder.java

XMLConfigBuilder.java

XMLMapperBuilder.java

 MappedStatements

 

 

二、创建SqlSession

 

返回包含configuration和Executor的DefaultSqlSession对象

DefaultSqlSessionFactory.java

Configuration.java

Executor.java

CachingExecutor.java 

 

三、获取接口的代理对象:MapperProxy.java

 

getMapper(), 使用MapperProxyFactory创建一个MapperProxy的代理对象,代理对象里面包含了:DefaultSqlSession(包含 Executor)

 

 

 

四、查询流程

 

 

 

 

 

快速开始:

一、maven依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.8</version>
</dependency>

 

二、构建全配置xml (mybatis-config.xml)

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="db.properties"></properties>
    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <!-- 控制全局缓存(二级缓存)-->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!-- <setting name="localCacheScope" value="STATEMENT"/> -->
       <setting name="localCacheScope" value="SESSION"/> </settings> <typeAliases> <typeAlias alias="blog" type="com.wuzz.domain.Blog" /> </typeAliases> 
<!--
    <typeHandlers>
      <typeHandler handler="com.wuzz.type.MyTypeHandler"></typeHandler>
    </typeHandlers>
   -->
<!-- 对象工厂 -->
  <!--
    <objectFactory type="com.wuzz.objectfactory.GPObjectFactory">
      <property name="wuzz" value="666"/>
    </objectFactory>
   -->
<!--
    <plugins>
      <plugin interceptor="com.wuzz.interceptor.SQLInterceptor"> <
        property name="wuzz" value="betterme" />
      </plugin>
      <plugin interceptor="com.wuzz.interceptor.MyPageInterceptor">
      </plugin>
    </plugins>
  -->

 <environments default="development">
  <environment id="development">
    <!-- 单独使用时配置成MANAGED没有事务 -->
    <transactionManager type="JDBC"/>
    <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="BlogMapper.xml"/>
   <mapper resource="BlogMapperExt.xml"/>
 </mappers>
</configuration>

 

1. Configuration.xml 是 mybatis 用来建立 sessionFactory 用的,里面主要包含了数据库连接相关东西,还有 java 类所对应的别名,

  比如<typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 这个别名非常重要,你在 具体的类的映射中,

  比如 User.xml 中 resultType 就是对应这里的。要保持一致,当然这里的 resultType 还有另外单独的定义方式,

  后面再说。

2.Configuration.xml 里面 的<mapper resource="com/yihaomen/mybatis/model/User.xml"/>是包含要映射的类的 xml 配置文件。

3.在 User.xml 文件里面 主要是定义各种 SQL 语句,以及这些语句的参数,以及要返回的类型等。

    • 对应class的xml中,property对应类的属性,column对应查询sql的项。

    • 问:mybatis mapper xml文件配置resultmap时,id行和result行有什么区别?
      答:id和result都是映射单列值到一个属性或字段的简单数据类型。
      唯一不同是:id是作为唯一标识的,当和其他对象实例对比的时候,这个id很有用,尤其是嵌入缓存和结果映射时。

    • 问:resultMap和resultType的区别?
      答:MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap;
      resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用;
      但是resultType跟resultMap不能同时存在。
      在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。
      所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType所指定对象的属性,而当我们提供的返回类型是resultMap的时候,Mybatis就会根据我们配置的信息做映射。

 

三、构建mapper

 

四、构建运行程序

 

Mybatis的的工作原理和工作流程

1. mybatis的 核心配置文件

  配置数据源、事务管理方式、指定SQL映射文件的位置

2. SqlSessionFactory(会话工厂)

  根据核心配置文件生成的一个工厂对象

  作用: 创建SqlSession

3. SqlSession: 提供开发人员一个接口

  作用: 操作数据库(增删改查)

  a. Configuration对象

  b. dirty:true       sql语句执行完毕后,可以提交事务

                 false     sql语句执行错误,可以回滚事务

4. Executor执行器对象 : 是一个在SqlSession内部使用的接口,负责对数据库的具体操作

     创建statement对象, 在创建过程中,依靠MapperStatement对象将赋值内容与SQL占位符进行绑定。

5. mapped statement(底层封装工具类)

  负责生成具体的SQL命令以及对查询结果集的二次封装

 

Mybatis核心概念:

  configuration、sqlSessionFactory、session、Executor、 MappesStatement、StatementHandler、ResultSetHandler

  

configuration  存储配置信息
sqlSessionFactory  创建SqlSession对象
sqlsession  提供增删改查方法
Executor  创建Statement对象
MappesStatement  将赋值内容与sql占位符进行绑定,一个MappesStatement代表一个增、删、改、查标签的详细信息
StatementHandler  
ResultSetHandler  
   

 

mybatis的使用:

mybatis的配置项:

 application.properties:

#数据源配置‘
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///test
spring.datasource.username=root
spring.datasource.password=root

#mybatis映射
mybatis.type-aliases-package=com.feng.ssm.dto

#配置日志
#打印dao层日志
logging.level.com.feng.ssm.dao=debug

logging.path=
logging.file=stu.log

 

具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按下面列举的顺序查找)。 如果一个都未找到,日志功能就会被禁用。
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
当一个系统有多个日志的时候,如果想用低等级的框架,就需要在mybatis配置文件中写上这句话声明一下:

<setting name="logImpl" value="LOG4J"/>

 

Mybaits的优缺点:

      优点:1.能够与Spring很好的集成;

                 2.很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。

                 3.与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;

                 4.基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;

                    提供XML标签,支持编写动态SQL语句,并可重用。

       缺点:1.SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。

                  2.SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

 

 

底层原理:

      mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory
 (SqlSessionFactory是线程安全的);然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成
对数据库的CRUD和事务提交,之后关闭SqlSession。

 

 

 

MyBatis的SQL查询流程:

      创建sqlSession的过程其实就是根据configuration中的配置来创建对应的类,然后返回创建的sqlSession对象。调用selectOne方法进行SQL查询,selectOne方法最后调用的是selectList,在selectList中,会查询configuration中存储的MappedStatement对象,mapper文件中一个sql语句的配置对应一个MappedStatement对象,然后调用执行器进行查询操作。

 

     

MyBatis缓存:

       MyBatis提供查询缓存,用于减轻数据库压力,提高性能。MyBatis提供了一级缓存和二级缓存。

 

 

  一级缓存: 是SqlSession级别的缓存,每个SqlSession对象都有一个哈希表用于缓存数据,不同SqlSession对象之间缓存不共享。同一个SqlSession对象对象执行2遍相同的SQL查询,在第一次查询执行完毕后将结果缓存起来,这样第二遍查询就不用向数据库查询了,直接返回缓存结果即可。MyBatis默认是开启一级缓存的。

  二级缓存: 是mapper级别的缓存,二级缓存是跨SqlSession的,多个SqlSession对象可以共享同一个二级缓存。不同的SqlSession对象执行两次相同的SQL语句,第一次会将查询结果进行缓存,第二次查询直接返回二级缓存中的结果即可。MyBatis默认是不开启二级缓存的,可以在配置文件中使用如下配置来开启二级缓存。

 

posted @ 2021-08-31 07:37  IT6889  阅读(75)  评论(0编辑  收藏  举报