Mybatis框架:原理解析

目录

一、原生jdbc  —  jdbc utils工具类 —  ORM框架

二、Mybatis是什么?

三、Mybatis和Hibernate区别和应用场景

四、Mybatis框架原理

五、SqlMapConfig.xml

1、properties属性

2、settings全局参数配置

3、typeAliases(别名)

4、typeHandlers(类型处理器)

5、mappers(映射配置)

六、Mapper.xml

1、#{}与${}

2、几种传递

3、几种输出

七、动态sql (if、where、foreach、sql片段)

八、延迟加载

九、缓存

1、一级缓存

2、二级缓存


 

 

一、原生jdbc  —  jdbc utils工具类 —  ORM框架

1、原生jdbc

步骤:

  1. 加载数据库驱动
  2. 创建并获取数据库链接
  3. 创建jdbc statement对象
  4. 设置sql语句
  5. 设置sql语句中的参数(使用preparedStatement)
  6. 通过statement执行sql并获取结果
  7. 对sql执行结果进行解析处理
  8. 释放资源(resultSet、preparedstatement、connection)

原生jdbc存在的问题

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

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

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

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

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

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

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

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

2、JDBCUtils

3、ORM框架

       ORM:将java程序中的对象自动持久化到关系数据库中

    (1)JPA:本身是一种ORM规范,不是ORM框架,由各大ORM框架提供实现。

    (2)Hibernate:ORM框架,设计灵巧,性能一般,文档丰富。

    (3)MyBatis:本是apache的一个开源项目iBatis,提供的持久层框架包括sql maps和DAO,允许开发人员直接编写sql等。
 

 

二、Mybatis是什么?

       MyBatis是一个持久层的框架,是apache下的顶级项目。

       MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。

       MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码

      Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

      Mybatis让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成 (半自动化(逆向工程),大部分需要程序员编写sql) 。

 

三、Mybatis和Hibernate区别和应用场景

 

Hibernate是一个标准ORM框架(对象关系映射), 入门门槛较高,

                     不需要程序写sql,sql语句自动生成了, 对sql语句进行优化、修改比较困难。

                     应用场景:适用与需求变化不多的中小型项目,比如:后台管理系统,ERP(企业资源计划)、ORM(对象关系映射)、OA(办公自动化)等

                     Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

 

Mybatismybatis是一个不完全的ORM框架(因为也有部分映射功能),学习门槛低,简单易学

                 虽然程序员自己写sql, mybatis 也可以实现映射(输入映射、输出映射)。

                 专注的是sql本身,需要程序员自己编写sql语句, sql修改、优化比较方便

                 应用场景:适用与需求变化较多的项目,比如:互联网项目。

                 Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

                  Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

       企业进行技术选型(以低成本、高回报作为技术选型的原则),根据项目组的技术力量进行选择。

       总之:按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 

 

四、Mybatis框架原理

             


    流程:

   1.  mybatis配置:

            SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

             mapper.xml 文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

    2. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

    3. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

    4. mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

    5. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。

         mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

    6. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,

         Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

     7. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,

         Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

 

            通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory

            通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)

           SqlSession是一个面向用户(程序员)的接口。 SqlSession中提供了很多操作数据库的方法(发出sql:增、删、改、查)

如:selectOne(返回单个对象)、selectList(返回单个或多个对象)

 

 

五、SqlMapConfig.xml

    mybatis的全局配置文件SqlMapConfig.xml,配置内容如下(有顺序)

                properties(属性)

                settings(全局配置参数)

                typeAliases(类型别名)

                typeHandlers(类型处理器)

                objectFactory(对象工厂)

                plugins(插件)

                environments(环境集合属性对象)

                environment(环境子属性对象)

               transactionManager(事务管理)

                dataSource(数据源)

                mappers(映射器)

 

1、properties属性

      将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值。

      在SqlMapConfig.xml中就不需要对数据库连接参数硬编码

      将数据库连接参数只配置在db.properties中原因:方便对参数进行统一管理,其它xml可以引用该db.properties。

 

        注意: MyBatis 将按照下面的顺序来加载属性:

                         在 properties 元素体内定义的属性首先被读取。

                         然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

                         最后读取parameterType传递的属性,它会覆盖已读取的同名属性。

 

           建议:不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中。

                       在properties文件中定义属性名要有一定的特殊性,如:XXXXX.XXXXX.XXXX  如jdbc.username

 

2、settings全局参数配置

             mybatis框架在运行时可以调整一些运行参数。比如:开启二级缓存、开启延迟加载。。

            全局参数将会影响mybatis的运行行为。

3、typeAliases(别名)

         在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。

         如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。

        mybatis默认支持别名:

         

别名

映射的类型

_byte

byte

_long

long

_short

short

_int

int

_integer

int

_double

double

_float

float

_boolean

boolean

string

String

byte

Byte

long

Long

short

Short

int

Integer

integer

Integer

double

Double

float

Float

boolean

Boolean

date

Date

decimal

BigDecimal

bigdecimal

BigDecimal

4、typeHandlers(类型处理器)

           mybatis中通过typeHandlers完成jdbc类型和java类型的转换

           通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.

           mybatis支持类型处理器:

类型处理器

Java类型

JDBC类型

BooleanTypeHandler

Booleanboolean

任何兼容的布尔值

ByteTypeHandler

Bytebyte

任何兼容的数字或字节类型

ShortTypeHandler

Shortshort

任何兼容的数字或短整型

IntegerTypeHandler

Integerint

任何兼容的数字和整型

LongTypeHandler

Longlong

任何兼容的数字或长整型

FloatTypeHandler

Floatfloat

任何兼容的数字或单精度浮点型

DoubleTypeHandler

Doubledouble

任何兼容的数字或双精度浮点型

BigDecimalTypeHandler

BigDecimal

任何兼容的数字或十进制小数类型

StringTypeHandler

String

CHARVARCHAR类型

ClobTypeHandler

String

CLOBLONGVARCHAR类型

NStringTypeHandler

String

NVARCHARNCHAR类型

NClobTypeHandler

String

NCLOB类型

ByteArrayTypeHandler

byte[]

任何兼容的字节流类型

BlobTypeHandler

byte[]

BLOBLONGVARBINARY类型

DateTypeHandler

Datejava.util

TIMESTAMP类型

DateOnlyTypeHandler

Datejava.util

DATE类型

TimeOnlyTypeHandler

Datejava.util

TIME类型

SqlTimestampTypeHandler

Timestampjava.sql

TIMESTAMP类型

SqlDateTypeHandler

Datejava.sql

DATE类型

SqlTimeTypeHandler

Timejava.sql

TIME类型

ObjectTypeHandler

任意

其他或未指定类型

EnumTypeHandler

Enumeration类型

VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。

 

5、mappers(映射配置)

 

法1:通过resource加载单个映射文件

         

法2:通过mapper接口加载单个mapper

       规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中。

       此规范使用的前提是:使用的是mapper代理方法

       按照上边的规范,将mapper.java和mapper.xml放在一个目录 ,且同名。

法3:批量加载mapper (推荐使用)

      指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载

      遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中

      上边规范的前提是:使用的是mapper代理方法

 

 

六、Mapper.xml

         Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

1、#{}与${}

        #{}:表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,即向prepareStatement中的预处理语句中设置参数值,自动进行java类型和jdbc类型转换。

        #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

        #{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

 

       通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。使用${}不能防止sql注入,但是有时用${}会非常方便。

<!-- 根据名称模糊查询用户信息 -->
<select id="selectUserByName" parameterType="string" resultType="user">
    select * from user where username like '%${value}%'
</select>

   如果本例子使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用${}在sql中拼接为%的方式则在调用mapper接口传递参数就方便很多。

//如果使用占位符号则必须人为在传参数中加%
List<User> list = userMapper.selectUserByName("%管理员%");


//如果使用${}原始符号则不用人为在参数中加%
List<User>list = userMapper.selectUserByName("管理员");

    再比如order by排序,如果将列名通过参数传入sql,根据传的列名进行排序,应该写为:ORDER BY ${columnName},如果使用#{}将无法实现此功能。

 

2、几种传递

    传递简单类型

    传递pojo对象

    传递pojo包装对象

    传递hashmap

3、几种输出

resultType:输出简单类型

     resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

resultMap

      如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

      resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

 

七、动态sql (if、where、foreach、sql片段)

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

       通过mybatis提供的各种标签方法实现动态拼接sql。

 

八、延迟加载

    resultMap可以实现高级映射(使用association、collection实现一对一一对多映射),

    association、collection具备延迟加载功能。

    延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

    需求:如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

 

 

九、缓存

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

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

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

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

     关系图如下:

                       

1、一级缓存

     原理:

                  

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

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

        如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读(读到另一个事务的未提交更新数据,即读取到了脏数据)

       第二次发起查询用户id为1的用户信息,先去找缓存中找是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。(若没有就去数据库中查)

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

 

2、二级缓存

   原理:

         

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

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

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

 

       二级缓存与一级缓存区别:二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。 UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

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

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

     注意,楼主要说话啦:

              生产中,大部分使用的是独立的缓存服务器,使用第三方缓存组件替代原生二级缓存,原生二级缓存是有些鸡肋的。

 

    注意,楼主又要说话啦:

               思想很重要!   框架只是对思想的实现

               设计模式很重要! 框架里大量应用了设计模式,后期会再针对性的写篇文章

               生产实践很重要!

 

 

 

 

以上,个人总结,如有错误之处,敬请指出?

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值