持久层框架——Mybatis知识点总结

用来做什么?
持久层框架——Mybatis知识点总结
将数据库中的数据映射到对象中,将对象中的属性映射到数据库字段

特点:可以只写dao接口不写实现类
sql由开发人员编写,可以充分发挥写sql的技巧,提供了很高的灵活性,
需要传入参数,实体对象也可以,变量也可以
mybatis会自动拼接sql和参数,拿到数据库中执行,将执行结果依靠反射机制封装成你需要的实体类或是List返回给你。
持久层框架——Mybatis知识点总结
sql写在哪里?
1、xml(常用,易于维护,易于拼接参数)
2、注解

如何实现Dao接口?
1、Mapper自动实现Dao接口(常用:节省出精力去关注sql的编写)
2、API编程方式实现Dao接口

mapper(xml)文件均对应一个dao层接口类,使用namespace对应具体的接口类,每个接口方法根据实际的操作类型选择对应的标签编写sql,标签id对应方法名,resultType对应返回值类型(返回实体类名),parameterType对应参数类型,sql中参数使用#{参数名}与sql拼接。

spring整合mybatis

为什么要整合?(mybatis优点,xml提供sql,mapper实现dao接口)
    更少的编码
        mybatis可以在dao层只写接口不写实现,方法返回值类型使得mybatis可以帮我们映射封装结果集,方法名对应实际操作类型使得mybatis知道我们要做什么,参数加sql构成实际行为过程。
    更少的配置
        别名:mybatis自动实现了包扫描,开发人员只需要提供类名,mybatis会根据类名自动扫描到具体的类
        配置扫描:项目中会有很多dao接口,每个接口类对应一个xml配置文件,将这些文件统一放在一个目录下,配置该目录到配置扫描,mybatis就可以扫描该目录下所有配置文件,不需要开发人员一个xml一个xml去配置维护。
        dao实现:mybatis自动实现dao接口,然后自动注入到spring的bean容器,否则需要在spring中一个一个配置dao的实现类到bean容器中.       
    足够的灵活性:sql自己编写,*传参,结果集自动赋值封装

整合步骤:
spring配置文件中:(一个context三个bean)
1、引入配置数据库所需相关参数的properties文件
2、配置数据库连接池:设置连接池公共属性(驱动、url、用户、密码)以及连接池私有属性(最大连接数、最小连接数、关闭连接是否提交、获取连接超时时间、获取连接重试次数)
3、配置sqlSessionFactory(注入数据源,即数据库连接池配置的beanId.配置mybatis全局配置文件路径,配置mybatis的实体类包扫描路径,配置dao层的mapper映射文件扫描路径)
4、配置Dao接口包扫描bean(MapperScannerConfigure),并且注入sqlSessionFactory,配置dao包扫描路径

Mapper开发原则:
1、每一个Dao接口对应一个mapper.xml,该xml的namespace对应dao接口的全限定名
2、dao接口里的方法名对应mapper.xml中的statement的id,(select、update等标签每个都对应一个statement对象)
3、dao接口中方法的参数类型必须与xml中statement的parameterType保持一致
4、dao接口中方法的返回值类型必须与xml中statement的resultType保持一致

DAO接口里的方法传入参数不同时不能重载!因为mapper自动实现接口的原理是根据xml的namespace(接口类全限定名)以及statement的id(接口类的方法名)拼接起来作为key去定位一个唯一的MappedStatement

实现原理:Dao接口的工作原理就是JDK动态代理。Mybatis运行时通过session.getMapper()获取代理对象,代理对象会拦截接口方法,在其invoke()方法中根据接口的全限定名和方法名去xml中取得对应的sql执行,
然后将执行结果返回。

Mybatis动态sql:
对于一些复杂的查询会涉及多个查询条件,但这些条件可能存在也可能不存在。不使用持久层框架时需要在代码中判断并拼接sql。Mybatis的动态sql就是解决这个问题的方式,将sql判断拼接以标签的形式写在xml中进行逻辑判断和动态拼接,必然比写在代码中便于维护。
9中动态sql标签:trim、where、set、foreach、if、choose、when、otherwise、bind
工作原理:使用OGNL从配置的参数对象中获取具体属性并计算表达式的值,再根据计算结果 动态拼接sql。


Mybatis对分页的支持:
Mybatis使用RowBounds对象进行分页,是针对ResultSet结果集执行的内存分页。物理分页需自己编写分页sql或使用分页插件,比如pagehelper。
(pagehelper使用时需要在后紧跟mybatis的查询操作,或者对分页参数进行手动清除。pagehelper使用了静态的ThreadLocal参数,分页参数适合线程绑定的。但如果使用pagehelper绑定了分页参数却没有执行查询操作,会导致该参数没有被消费,一直保留在该线程上,当这个线程再次使用时,可能会导致莫名其妙的分页。)

Mybatis对延迟加载的支持以及延迟加载的实现原理:
mybatis仅支持对一对一或一对多关联关系中关联对象的延迟加载。通过在mybatis配置文件中配置lazyLoadingEnabled为true或false来控制是否启用。
实现原理(同Hibernate):使用CGLIB创建目标对象的代理对象,在调用目标对象中关联对象的方法前,先进入拦截器,其invoke方法判断关联对象是否为null,若为null,则单独发送事先保存好的该关联对象的查询sql,把关联对象查询出来,然后再调用关联对象的方法,这是关联对象就有值了,实现了关联对象的延迟加载。

Mybatis中sqlSession的创建过程:
1、从配置文件中获取Environment对象;
2、从环境对象中获取数据源;
3、从环境对象中获取事务工厂对象;
4、在数据源对象上获取数据库链接对象Connection;
5、在取得的链接对象上创建事务对象;
6、创建Executor对象,sqlSession对象的所有操作都通过Executor对象完成;
7、创建sqlSession对象。

Mybatis执行器:
Executor对象在mybatis中有三种基础类别:
    1、SimpleExecutor简单执行sql,没什么特别。每执行一次sql就会开启一个statement对象,执行完立刻关闭。
    2、ReuseExecutor,重用statement对象,以sql作为key从一个map中查找statement对象,获取到就直接使用,不存在就创建,使用完不关闭,放置于map中以供下一次使用。
    3、BatchExecutor,对非select操作执行批处理操作,缓存多个statement对象,等待executeBatch()方法执行。
Executor对象是被动态创建的,具体根据配置生成三种基础类别之一。若是开启缓存,缓存是默认被开启的,就会将创建的基础类别执行器作为构造器参数,生成加强的CachingExecutor对象。缓存执行器加强的行为在于,在查询数据库前先查询缓存,若未查到,则使用传入的基础执行器查询数据库。

Mybatis的缓存机制:内部缓存使用HashMap,key为hashCode+sqlId+sql语句,value为查询结果映射生成的java对象。
一级缓存:SqlSession级别(即Concetion级别),每个sqlSession互相独立,mybatis默认开启,基于HashMap的本地缓存。
当同一个sqlSession执行两次相同的查询操作时,第一次会将查询结果写到缓存,第二次直接从缓存中获取。当sqlSession执行写操作并提交到数据库时会清空缓存,保证缓存数据的最新。
二级缓存:Mapper级别(即根据mapper.xml的namespace划分),多个sqlSession可以共用二级缓存,基于HashMap进行存储,需在mapper.xml中手动配置开启该mapper的二级缓存。
当不同的sqlSession多次执行相同namespace下的sql查询时,会执行同样的sql语句,会查询第一次执行后缓存的结果,不查询数据库。

Mybatis与Hibernate区别:
1、Mybatis是半自动ORM框架,需要自己编写sql。但是正因为这样,可以灵活的编写sql语句,方便优化,也因为这样,数据无关性为0,需要实现支持多套数据库的sql。
2、Hibernate数据库无关性好,不需要写sql,开发效率高。