mybatis学习笔记

 
第一部分:自定义持久层框架
 
1.1 原始JDBC编写步骤及存在问题
编写步骤(查询):
加载数据库驱动--》通过驱动管理类获取数据库连接--》定义sql语句--》获取预编译statement--》设置参数--》向数据库发出sql执行查询,查询结果集--》遍历结果集,封装实体--》关闭资源
 
存在问题:
1)频繁的创建、释放数据库连接会造成系统资源的浪费,从而影响系统性能。
2)sql语句存在硬编码、使用preparedStatement向有占位符传参数存在硬编码、结果集解析的时候存在硬编码,造成代码不易维护。
 
1.2 问题解决思路
1)使用数据库连接池初始化连接资源
2)将sql抽取到xml文件中
3)使用反射、内省等底层技术,将数据库字段与实体属性进行自动映射。
 
1.3 自定义框架设计
使用端:
提供核心配置文件:
SqlMapConfig.xml:存放数据源信息,引入Mapper.xml
Mapper.xml:存放sql语句的配置信息
 
框架端:本质是对jdbc的封装
1)读取配置文件
首先以流的形式读取配置文件,然后将字节输入流存进两个javabean对象,方便后续的操作。
两个javabean如下:
Configuration:存放数据库基本信息,Map<namespace+"."+id,mappedstatement>
MappedStatement:id标识,sql语句,statement类型(select,insert,update,delete),输入参数java类型,输出参数java类型
 
2)解析配置文件
创建SqlSessionFactoryBuilder类
方法: SqlSessionFactory build()
第一:使用dom4j解析配置文件,将解析出来的内容封装到Configuration和MappedStatement中
第二:创建SqlSessionFactory的实现类DefaultSqlSessionFactory
 
3)创建SqlSessionFactory
方法:openSession() :获取SqlSession接口的实现类实例对象
 
4)创建SqlSession接口及实现类DefaultSqlSession,主要封装crud方法
方法:selectList(String stateMentId, Object param):查询所有
selectOne(String stateMentId, Object param):查询单个
...
具体实现:封装jdbc完成对数据库的操作
5)Executor,实现类SimpleExecutor
 
涉及到的设计模式:
Builder构建者模式,工厂模式,代理模式
 
1.4 自定义框架实现
动手敲一下代码。。。
 
1.5 自定义框架优化
上述自定义框架存在的问题:
1) dao的实现类里存在重复代码,整个操作的过程模板重复(创建sqlSession,调用sqlSession,关闭sqlSession)
2) dao实现类中存在硬编码,调用sqlSession方法时,参数statement的id硬编码
 
解决方案:使用代理模式来创建接口的代理对象(不管代理对象调用何方法,都会转到invoke())
 
代理模式注意事项:
  • Mapper.xml文件中的namespace与Mapper接口中的全限定名相同
  • Mapper.xml中定义的每个statement的id与Mapper接口的方法名相同
  • Mapper.xml中定义的每个sql的parameterType与Mapper接口的输入参数类型相同
  • Mapper.xml中定义的每个sql的resultType与Mapper接口的输出参数类型相同
 
Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,根据类的全限定名+方法名,唯一定位到一个MapperStatement并调用执行器执行所代表的sql,然后将sql执行结果返回。
 
Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。
 
 
第二部分:Mybatis相关概念
 
Mybatis是一款优秀的基于ORM(对象关系映射)的半自动化轻量级的持久层框架,SQL与JAVA编码分离。
 
第三部分:Mybatis基本应用
 
3.1 开发步骤
1) 添加Mybatis坐标
2)创建user数据库表
3)编写user实体类
4)编写映射文件UserMapper.xml
5)编写核心配置文件SqlMapConfig.xml
6)编写测试类
 
注:增加,更新,删除操作涉及数据库变化,要使用sqlSession对象显示的提交事务,
即sqlSesison.commit();因为sqlSessionFactory.openSession()默认开启一个事务,但不会主动提交。
如果需要它主动提交,需要调用它的有参构造方法sqlSessionFactory.openSession(true).
 
 
3.2 Mybatis映射文件概述
0
3.3 MyBatis核心配置文件层级关系
 
0
3.4 Mybatis核心配置文件SqlSessionConfig.xml解析
1)environments标签
数据库环境的配置,支持多配置
0
其中:
事务管理器transactionManagee有两种类型:JDBC和MANAGED
数据源datasource有三种类型:POOLED,UNPOOLED,JNDI
 
2)mapper标签
该标签的作用是加载映射,加载方式如下:
  • 使用相对类路径的资源引用,例如:
 
 
  • 使用完全限定资源定位符(url),例如:
 
 
  • 使用映射器接口实现类的完全限定类名,例如:
 
 
  • 将包内的映射器接口实现全部注册为映射器,例如
 
 
3)properties标签
用于加载外部的properties文件,习惯上将数据源的信息单独抽取成一个properties配置文件
 
4)typeAliases标签
类型别名
 
 
3.5 mybatis 常用API介绍
SqlSession工厂构建器SqlSessionFactoryBuilder
常用API: SqlSessionFactory build(IputStream, inputStream)
SqlSession工厂对象SqlSessionFactory
常用API:openSession()(需要手动提交事务)或openSesison(true)(自动提交事务)
SqlSession会话对象
常用APi:增删改查方法。。。
 
 
3.6 Mybatis的Dao层实现方式
 
1)传统开发方式
需要编写dao接口及实现类(实现类有重复代码,且statementId存在硬编码问题)
 
2)代理开发方式
开发人员只需要编写Mapper接口(相当于dao接口),由Mybatis框架根据接口定义生成动态代理对象,代理对象的方法体同上面的dao接口实现类的方法。
Mapper接口需要遵循以下规范:
  • Mapper.xml文件中的namespace与Mapper接口中的全限定名相同
  • Mapper.xml中定义的每个statement的id与Mapper接口的方法名相同
  • Mapper.xml中定义的每个sql的parameterType与Mapper接口的输入参数类型相同
  • Mapper.xml中定义的每个sql的resultType与Mapper接口的输出参数类型相同
 
3.7 动态sql语句
 
 
 
and id=#{id}
 
...
 
 
 
 
#{id}
 
 
 
sql片段抽取
 
第四部分:Mybatis复杂映射开发
一对一配置
一对多配置
多对多配置
 
第五部分:Mybatis注解开发
@Insert:实现新增 @Update:实现更新 @Delete:实现删除 @Select:实现查询 @Result:实现结果集封装 @Results:可以与@Result 一起使用,封装多个结果集 @One:实现一对一结果集封装 @Many:实现一对多结果集封装
 
第六部分:Mybatis缓存
 
一级缓存和二级缓存底层的数据结构都是HashMap
Mybatis默认实现的缓存类是PerpetualCahe
自定义缓存类必须实现Cache类
 
 
6.1 一级缓存
Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Mabits默认开启一级缓存。 在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。 当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。 每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。
Mybatis的内部缓存使用一个HashMap,key(statementId+rowBounds参数+sql语句)。Value为查询出来的结果集映射成的java对象。 SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。
0
 
6.2 二级缓存
二级缓存的原理同一级缓存
但二级缓存是基于Mapper文件的namespace的,也就是说多个sqlSession可以共享一个Mapper中的二级缓存区域,
并且,如果两个Mapper的namespace相同,即使是两个mapper,那么这两个Mapper中执行sql查询的数据也将保存到相同的二级缓存区域中。
 
二级缓存默认是关闭的,需要手动开启!!
开启二级缓存步骤:
1)首先在全局配置文件SqlMapConfig.xml文件中加入以下代码:
 
 
 
2) 其次在Mapper.xml中开启缓存
< cache>
 
开启二级缓存后,对应的POJO类需要实现序列化接口serializable,为了将缓存数据取出来执行反序列化操作,
因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们再取这个缓存的时候,就需要反序列化了。
 
当一级缓存和二级缓存同时存在:先查询二级缓存再查询一级缓存,因为一级缓存的实现在BaseExecutor,而二级缓存的实现在CachingExecutor,CachingExecutor是BaseExecutor的装饰器
 
userCache和flushCache
在statement中设置userCahce = "false"可以禁用当前select语句的二级缓存。useCahce默认是true。
在statement中设置flushCache="true",可以刷新缓存,默认是true。在mapper的同一个namespace中,如果有其它的insert,update,delete操作数据后需要刷新缓存,如果不执行缓存会存在脏读。
 
二级缓存的默认实现类是PerpetualCache
 
6.3 二级缓存整合redis
mybatis自带的二级缓存仅支持单服务器工作,无法实现分布式缓存。
分布式缓存:在几个不同的服务器之间,我们使用第三方框架,将缓存存进第三方框架中(redis,memcached,ehcache),然后无论有多少台服务器,我们都能从缓存中获取数据。
 
mybatis提供了一个针对cache接口的redis实现类,该类存在mybatis-redis包中
需要在mapper.xml 中加入cache的类型指向
 
mybais-redis在存数据的时候,是使用的hash结构,把hash的id作为这个hash的key(hash的key在mybatis中就是mapper中的namespace);
这个mapper中的查询数据作为hash的filed,需要缓存的内容直接使用serializeUtil存储,serializeUtil和其它序列化类差不多,负责对象的序列化和反序列化。
 
 
第七部分:Mybatis插件
 
7.1 插件介绍
Mybatis四大核心对象:Executor,StatementHandler,ParameterHandler,ResultSetHandler
Mybatis支持用插件对四大核心对象进行拦截,对Mybatis来说,插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的动态代理实现的,
换句话说,Mybatis的四大对象都是代理对象。
 
Mybatis所允许拦截的方法如下:
  • 执行器Executor(update,query,commit,rollback等方法)
  • Sql语法构建器StatementHandler(prepare,parameterize,batch,updates,query等方法)
  • 参数处理器ParameterHandler(getParameterObject,setParameters方法)
  • 结果处理器ResultSetHandler(handleResultSets,handleOutputParameters等方法)
 
7.2 Mybatis插件原理
 
当我们定义一个插件,并在SqlMapConfig.xml增加插件配置后,这样Mybatis在启动的时候就可以加载插件,并保存插件实例到相关对象(InterceptorChain拦截器链)中.
待准备工作完成后,Mybatis处于就绪状态。我们再执行sql的时候,需要先通过DefaultSqlSessionFactory创建SqlSession.
Execoutor实例会在创建SqlSession的过程中被创建,Executor实例被创建完毕之后,Mybatis会通过JDK动态代理为实例生代理类,
这样,插件逻辑即可以在Executor相关方法调用前被调用。
 
7.3 自定义插件
自定义插件需要实现Interceptor接口,并重写 Object intercept(Invocation invocation)方法和 Object plugin(Object target)及void setProperties(Properties properties)方法
0
 
0
 
7.4 pageHelper分页插件
 
开发步骤:
1)导入通用的pageHelper坐标
2)在Mybatis核心配置文件SqlMapConfig.xml中配置pageHelper插件
3)测试分页数据获取
 
7.5 通用Mappper
通用mappper就是为了解决单表的增删改查,基于mybatis的插件机制,开发人员不需要写sql,不需要在dao的增加方法,需要写好实体类,就能支持增删改查方法。
具体参考老师的笔记!!
 
第八部分:Mybatis架构原理
 
8.1 功能架构分层
Mybatis的功能架构可分为三层:
1)API接口层
Mybatis与数据库交互有两种方式:
a)使用传统的Mybatis提供的API
b)使用Mapper的代理方式
2)数据库处理层
负责具体的sql查找,sql解析,sql执行和执行结果映射等操作。它主要的目的是根据调用的请求完成一次性数据库操作。
3)基础支撑层
负责最基础的功能支撑,包括连接管理,事务管理,配置加载和缓存处理。
 
8.2 主要构件及其关系
  • SqlSesison :作为Mybatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库的增删改查功能。
  • Executor:Mybatis执行器,是Mybatis调度的核心,负责SQl语句的生成和查询缓存的维护
  • StatementHandler:封装了JDBC的statement操作(设置参数,将Statement结果集转成list集合)
  • ParameterHandler:负责对用户传递的参数转成JDBC Statement所需要的参数
  • ResultSetHandler:负责将JDBC返回的ResultSet结果集转换成List类型的集合
  • TypeHandler:负责Java类型和JDBC数据类型之间的映射和转换
  • MappedStatement:维护了一条
posted @ 2021-05-08 18:24  冰湖一角  阅读(196)  评论(0编辑  收藏  举报