MyBatis框架总结

来源:互联网 发布:化工制图软件 编辑:程序博客网 时间:2024/05/29 19:31
MyBatis

1.对原生态JDBC程序(单独使用JDBC开发)的问题总结
2.MyBatis框架原理
3.MyBatis入门程序
        用户的CRUD操作
4.MyBatis开发的两种方法
        原始DAO开发方法(需要编程DAO接口和DAO实现类)(掌握)
        MyBatis的Mapper接口(相当于DAO接口)代理开发方法(掌握)
5.MyBatis配置文件SqlMapConfig.xml
6.MyBatis核心
        MyBatis输入映射(掌握)
        MyBatis输出映射(掌握)
7.MyBatis动态SQL(掌握)
8.MyBatis延迟加载
9.MyBatis查询缓存(一级缓存,二级缓存)
10.MyBatis和Spring进行整合(掌握)
11.MyBatis逆向工程

框架架构图




parameterType
指定输入参数的数据类型
此数据类型对应数据库中表里的字段的数据类型

resultType
指定输出结果所映射的java对象类型

#{}和${}
#{}表示一个占位符,#{}接收输入参数,参数类型可以是简单类型(int,String等基本数据类型),pojo,HashMap等
        如果接收简单类型,#{}中可以写成#{value}或者其他名称
#{}接收pojo对象值,是通过OGNL()读取对象中的属性值,通过属性.属性.属性的方式获取对象属性值

${}表示一个拼接符号,会引起SQL注入,所以不建议使用
${}接收输入参数,参数类型可以是简单类型(int,String等基本数据类型),pojo,HashMap等
        如果接收简单类型,${}中只能写成${value}
#{}接收pojo对象值,是通过OGNL()读取对象中的属性值,通过属性.属性.属性的方式获取对象属性值

添加一条数据库记录返回自增主键值(MySQL)
将插入数据的主键返回到pojo对象中
【只适用于自增主键】
SELECT LAST_INSERT_ID():得到刚刚insert插入进数据库的记录的主键值
            
keyProperty:将查询到的主键值设置到parameterType指定的对象的id属性中
order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
resultType:指定SELECT LAST_INSERT_ID()的结果的数据类型

【注】:若是Oracle数据库的话,把LAST_INSERT_ID()替换成Oracle中获取序列的方法即可。


Hibernate和MyBatis本质的区别和应用场景
Hibernate:是一个标准的ORM(对象关系映射)框架,入门门槛比较高,不需要程序员写SQL,其SQL语句是自动生成
难点:对SQL语句进行优化,修改比较困难。
应用场景:
        适用于需求变化不多的中小型的项目,比如:后台管理系统,ERP,ORM,OA等等

MyBatis:专注SQL本身,需要程序员自己编写SQL语句,SQL的修改和优化比较方便。
MyBatis是一个不完全的ORM框架,虽然程序员自己写SQL,但是MyBatis也可以实现映射(输入映射,输出映射)
难点:对SQL语法及数据库的了解需要多一些。
应用场景:
        适用于需求变化较多的项目,比如:互联网项目。
        
SqlSession的使用范围
SqlSessionFactoryBuilder
    将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder
    在需要创建SqlSessionFactory的时候,只需要new一次SqlSessionFactoryBuilder即可。
SqlSessionFactory
    通过SqlSessionFactory创建SqlSession,使用单例模式管理SqlSessionFactory(工厂一旦创建,使用一个示例)
    将来mybatis和spring整合后,使用单例模式管理SqlSessionFactory
SqlSession
    SqlSession是一个面向用户(程序员)的接口
    SqlSession中提供了很多操作数据库的方法,例如:selectOne,selectList
    SqlSession是线程不安全的,在SqlSession的实现类中除了有接口中的方法,还有数据域的属性
    SqlSession最佳的应用场合在方法体内,定义成局部变量

原始DAO开发方法(需要自己写DAO接口和实现类)
    需要向DAO实现类注入SqlSessionFactory
    在方法体内通过工厂创建SqlSession

总结问题:
    1.DAO接口实现类方法中存在大量的模版方法,设想能否将这些代码提取出来
    2.在调用sqlSession方法时将statement的id硬编码了(写死了)
    3.在调用sqlSession方法时传入的变量,由于sqlSession方法使用泛型,
        即使变量类型传入错误,在编译阶段也不会报错,不利于程序员开发
Mapper代理方法
    1.程序员需要编写mapper.xml文件
    2.程序员需要编写Mapper接口,需要遵循一些开发规范
        MyBatis就可以自动的将生成mapper接口实现类的代理对象
开发规范:
1.在mapper.xml中namespace等于mapper接口的地址
2.mapper.java接口中的方法名和mapper.xml中的statement的id一致
3.mapper.java接口中的方法的输入参数类型和和mapper.xml中的statement的parameterType的数据类型一致
4.mapper.java接口中的方法的输出参数类型和和mapper.xml中的statement的resultType的数据类型一致

问题总结:
代理对象内部调用selectOne或selectList
    如果mapper方法返回单个pojo对象,代理对象内部通过selectOne查询数据库
    如果mapper方法返回pojo对象的集合,代理对象内部通过selectList查询数据库
mapper接口方法参数只能有一个是否影响系统开发
    系统框架中,DAO层代码一定是被业务层共用的。
    即使mapper接口只有一个参数,可以使用包装类型的pojo满足不通的业务方法的需求
    【注意】
    持久层方法的参数可以使用包装类型(map...),service方法中建议不要使用包装类型(不利于业务层的维护和扩展)


MyBatis的全局配置文件SqlMapConfig.xml的相关配置如下:
properties(属性)
    将数据库链接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值
    在SqlMapConfig.xml中就不需要对数据库链接参数硬编码
    将数据库的链接参数db.properties中,原因:方便对参数进行统一管理,其他xml可以引用db.properties
    【注意】:MyBatis将按照下面的顺序来加载属性
                        1.在properties元素体内定义的属性首先被读取
                        2.然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性
                        3.最后读取parameterType传递的属性,它会覆盖已读取的同名属性
                        因此,通过parameterType传递的属性优先级最高,其次是resource或url加载的属性,
                        最后是properties元素体内定义的属性
    建议:不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中
                在properties文件中定义的属性名要有一定的特殊性,如:xxx.xxx.xxx
    
settings(全局配置参数)
    MyBatis框架在运行时可以调整一些运行参数,比如:二级缓存,延迟加载等等
    
typeAliases(类型别名)*
【MyBatis默认支持一下别名】
    别名                映射的类型
    _byte                    byte
    _long                    long
    _short              short
    _int                    int
    _integer            int
    _double                double
    _flaot                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
    
typeHandlers(类型处理器)
    MyBatis中通过typeHandlers完成jdbc类型和java类型的转换
    通常情况下,MyBatis提供的类型处理器满足日常需要,不需要自定义
    
objectFactory(对象工厂)
plugins(插件)
enviornments(环境集合属性对象)
    enviornment(环境子属性对象)
        transcationManager(事务管理)
        dataSource(数据源)
mappers(映射器)
    通过resource方法加载单一映射文件
    <mapper resource="sqlmap/User.xml"/>
    通过url加载本地文件系统中的映射文件
    <mapper url="file:///D:\xxx\xx\xxx.xml"/>
    通过mapper接口加载
    <mapper class=""/>
    
    
MyBatis的输入映射和输出映射
输入映射
    通过parameterType指定输入参数的数据类型
    数据类型可以是简单类型,HashMap,pojo类型
    
    pojo包装对象
    
    
输出映射
    使用resultType进行输出映射,只有在查询出来的列名和pojo中的属性名一致,该列才可以映射成功
    如果查询出来的列名和pojo中的属性名全部不一致,则返回中不会创建pojo对象
    只要查询出来的列名和pojo中的属性名有一个一致,就会创建pojo对象

    resultType还可以输出简单的数据类型(在查询结果只有一行且只有一列时)
    
    输出pojo对象
    输出pojo对象的列表
    不管是输出的pojo单个对象还是一个pojo对象列表,在mapper.xml中resultType指定的类型是一样的
    在mapper.java中指定的方法返回值类型不一样
    
    生成的动态代理对象中是根据mapper方法的返回值类型确定
    是调用selectOne(返回单个对象时调用)
    还是selectList(返回集合对象时调用)

    resultType还可以输出HashMap的类型
    示例:List<HashMap<Pojo>>
    map中的key就是列名
    map中的value就是值
    
    
    MyBatis中使用resultMap完成高级输出结果映射
    
    如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名做一个映射关系
    
    resultType必须列名和pojo对象的属性名一致才能输出
    resultMap则可以在列名和pojo对象的属性名之间建立对应关系后,就可以输出


MyBatis高级映射(一对一,一对多,多对一,多对多)

    使用resultType实现(简单)【无法实现延迟加载】
    
    使用resultMap实现(稍微复杂一点)【可以实现延迟加载】

    association完成一对一关联映射查询
    
    collection完成一对多关联映射集合对象
    
resultMap总结
作用:将关联查询信息映射到一个pojo对象中
场合:为了方便查询关联信息可以是用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息
            使用resultType无法将查询解雇哦影视到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap
collection
作用:将关联查询信息映射到一个list集合中
场合:为了方便查询关联信息可以使用collection将关联信息映射到list集合中
            比如:查询用户权限范围模块及模块下的菜单(一级+二级菜单)
                        可以使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中
                        这样做的目的是方便对查询结果集进行遍历
                        如果使用resultType无法将查询结果映射到list集合中
                        
延迟加载
1.什么是延迟加载
        延迟加载:先从单表查询,需要时再关联表去关联查询,大大提高数据库性能,
                            因为产线单表要比关联查询多张表速度快
2.使用collection和association实现延迟加载

MyBatis的缓存




一级缓存是sqlSession界别的缓存。在操作数据库的时候需要构造sqlSession对象,
在该对象中有一个数据结构(HashMap)用于存储缓存数据。
【注意】:不通的sqlSession直接的缓存数据区域(HashMap)是互不影响的


二级缓存是Mapper级别的缓存,多个sqlSession去操作同一个Mapper的SQL语句,
多个sqlSession操作数据库得到的数据会存在二级缓存区域,即多个sqlSession可以共用二级缓存
【注意】:二级缓存是跨sqlSession的。


一级缓存的工作原理
示例:第一次发起查询用户id为1的用户信息,MyBatis会先去缓存中找是否有id为1的用户信息,
            如果没有,则从数据库查询用户信息。得到用户信息后,将用户信息存储到一级缓存中。
            
            如果在sqlSession去执行commit操作(insert,update,delete),MyBatis会清空sqlSession中的一级缓存
            这样做的目的是为了让缓存中存储的是最新的数据,避免脏读(旧数据)
            
            第二次发起查询用户id为1的用户信息,先去缓存中找是否有id为1的用户信息,缓存中有,
            则直接从缓存中获取用户信息
            
MyBatis默认支持一级缓存,不需要在配置文件中配置

一级缓存的使用
        在实际开发中,是将MyBatis和Spring进行整合开发,事务控制是在Service中
        一个Service方法包括很多Mapper方法的调用
        如果是执行两次Service调用查询相同的用户信息,这时是不走一级缓存的
        【原因】:因为Service方法结束,sqlSession就会关闭,一级缓存就会清空

二级缓存的使用
        在实际开发中,首先要将MyBatis的二级缓存开启(默认不开启)
        二级缓存与一级缓存的工作原理基本一样
        区别在于:二级缓存的作用范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域
        各个Mapper会有各自的二级缓存区域,缓存的区域是按照namespace划分的。
        如果两个Mapper的namespace相同,那么这两个Mapper所执行的sql将会存在同一个二级缓存区域


useCache参数:
        使用useCache来禁用二级缓存
        使用场景:useCache针对每次查询都需要更新的数据SQL,要设置成useCache="false"
flushCache参数
        使用flushCache来清空当前namespace下的二级缓存即:flushCache="true"
        一般清空下,执行完commit的相关操作,都需要刷新相关缓存,flushCache="true"就表示刷新缓存
        这样就可以避免数据库脏读

MyBatis和第三方缓存框架整合

整合方法:MyBatis提供了一个cache接口,如果要实现自己的缓存逻辑,只要实现cache接口开发即可。
例如:MyBatis和Ehcache整合,MyBatis和Ehcache整合包中就有对MyBatis的cache接口的实现
            MyBatis默认实现的cache类叫:PerpetualCache
            <cache/>标签中的type属性就是指定cache接口的实现类型
            若要和Ehcache整合,需要配置type为Ehcache实现cache接口的实现类

二级缓存的应用场景
        对于访问多的查询请求并且用户对查询结果实时性要求不高,此时可采用MyBatis的二级缓存
                来降低数据库访问量,提高访问速度
        业务应用场景:耗时较高的统计分析SQL,如果查询昨天的消费清空,上个月的各种产品的销售清空
        实现方法:通过设置刷新的间隔时间(flushInterval),由MyBatis每隔一段时间自动清空缓存
                根据数据编号频率设置缓存的刷新时间,比如设置为30分钟,60分钟,24小时等等
                
二级缓存使用的局限性
        MyBatis二级缓存对细粒度的数据级别的缓存实现的不好
        比如:对商品信息进行缓存,由于商品信息查询访问量大,但要求用户每次都能查询最新的商品信息
                    此时如果使用MyBatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息
                    而不刷新其他商品的信息,因为MyBatis的二级缓存区域以Mapper为单位来划分
                    当一个商品信息变化会将所有商品信息的缓存数据全部清空。
                    解决此类问题需要在业务层根据需求对数据有针对性的做缓存处理





0 0
原创粉丝点击