mybatis复习小计
2020-06-12 本文已影响0人
可靠的千秋
JDBC
java连接数据库都要用jdbc,用数据库池也一样,池缓存连接。
流程
加载数据库驱动(不同厂商驱动不一致)
通过驱动,数据库配置,建立连接
预处理statement
设置参数,预处理可以用?占位
发送sql执行
返回结果
释放资源
缺点
硬编码,频繁创建间连接,浪费资源,封装结果集麻烦(需要内省,反射)
持久层框架解决问题:硬编码(配置文件),频繁创建连接(连接池),封装结果集(反射,内省)
持久层框架级别配置(mybatis.config),sqlconfig(*mapper.xml),其主要本质是对jdbc的封装,加载配置文件字节流,存储内存,然后解析xml,把对mybatis的配置,对数据库的连接,映射配置,缓存起来(configuration缓存mybatis.config解析出来的内容,mappedstatement缓存映射配置),sqlsessionFactory.opensession生产session,sqlsessionFactoryBuilder解析出来内容封装到容器中。创建salsession接口(内部defaultsession定义对数据库操作)。创建executor执行对数据库操作,执行的就是jdbc代码
mybatis(ORM框架),手写sql,避免了jdbc代码和手动设置参数及获得结果集,通过xml方式来配置
可通过注解/XMLmappper方式执行
缓存
一级缓存(作用于sqlsession),二级缓存(作用于mapper缓存)
一级缓存默认是开启的,如果之前查询过,那么第二次查询(同一个sqlsession的)会先从缓存中取,取不到,才去查询。底层其实是个map,key是由id(方法全路径加分页参数加sql),value就是查询结果返回的对象。1,一级缓存会失效,当调用了增删改方法,就默认会对事物进行提交,就会刷新缓存。2,clearcache()手动刷新一级缓存。
二级缓存原理一样(执行增删改会刷新缓存),也是个map,二级缓存基于namespace,多个sqlsession可以共享一个mapper的二级缓存。默认不开启。可添加配置<setting name="cacheenabled" value="true">或用注解方式@cachenamespace。开启二级缓存后,要实现serializable接口,实现序列化,反序列化。因为二级缓存存储介质多样,可内存,内硬盘。
useCache和flushCache,可配置useCache(用来设置某个statement禁用二级缓存的查询,每次查询都去库中,默认是true),flushCache默认为true,即默认查询出来的数据同步刷新替换缓存中的数据,设置false是就不替换。
二级缓存可自定义实现,实现Cache接口,实现里面的方法及可实现。可在里整合reids,mamcached,ehcache等缓存服务器,可用于分布式二级缓存实现,维护数据准确性。--rediscache类,redis实现二级缓存,内部结构用的hash
插件
mybatis 一般用于实现监控,分页,分表等功能,业务无感知插件的存在,无感植入插件,增强功能。
四大组件都有插件(Executor,StatementHandler,ParameterHandler,ResultSetHandler),可以用来来接其相应方法
执行器Executor(update,query,commit,rollback)
SQL语法构建器StatementHandler(prepare,parameterize,batch,update,query)方法
参数处理器ParameterHandler(getParameterObject,setParameters)
结果处理器ResultSetHandler(handleResultSets,handleOutputParameters)
创建四大组件时,会调用interceptorChain.pluginall进行返回(interceptor..plugin进行返回,放到拦截器链中),本质是通过拦截器实现,底层用jdk动态代理,为实例对象生成代理类,插件逻辑就通过代理对象增强中执行。
可自定义插件,实现interceptor接口,重写其方法,通过xml配置自定义插件全路径即可(主要是invoke方法进行拦截,invoke会检测呗拦截的方法是否再配置插件的拦截范围之内,若在,执行拦截逻辑,否则直接执行方法。)。
架构原理
mybatis架构分为三层
1,api接口层,提供给外部使用接口api,开发人员通过api操作数据库(两种数据库交互方式,1,传统的api,2,用mapper代理)
2,数据处理层,负责sql查找,解析,执行,结果的映射等,对数据库的操作。
(perameterhandler参数解析->sqlsourceSQL解析->ExecutorSQL执行->Resultsethandler结果处理和映射)
3,基础支撑层,负责基础的功能支撑,连接管理,事务管理,配置加载,缓存等处理,都是公共的东西,抽取出来,供上层调用。
总体流程
1,加载配置,主配置conf.xnl,mapper.xml。2,接受调用请求,mybatis的api,传入参数等。3,处理操作请求,根据SQL的ID查找对呀的MappedStatement,然后根据参数解析mappedstatement对象得到最终结果和传入参数,获得数据库连接,根据sql和参数执行sql,得到结果,然后根据结果映射的配置转换封装结果集,得到最终结果,释放资源。4,返回处理结果
mybatis代理方式
getMapper,通过动态代理工厂生成实例,动态代理返回了实例之后,我们可以调用他的mapper类中的方法,执行的是mapperProxy中的invoke方法
设计模式
Builder模式 --SqlSessionFactoryBuilder,Environment;
工厂方法模式 -- SqlSessionFactory,TransactionFactory,LogFactory
单例模式 -- ErrorContext,LogFactory
代理模式 -- mybatis的核心,MapperProxy,ConnectionLogger用jdk的动态代理,executor.loader包使用了cglib或者javassist延迟加载效果
组合模式 --SqlNode和各个子类ChooseSqlNode等
模板方式模式 -- BaseExecutor和SimpleExecutor还有BaseTypeHandler和所有子类 IntegerTypeHandler
适配器模式 --Log的mybatis接口和它对jdbc,log4j各种日志的适配实现
装饰者模式 --cache包中的,cache.decorators子包中的各个装饰者实现
迭代器模式 --PropertyTokenizer
builder模式,是将一个复杂的对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示,属于创建类模式,用于创建的对象比较复杂。和工厂模式不同,工厂模式会产出一个完成产品,builder会更加复杂对象的构建,甚至构建对象的一部分。使用多个简单对象一步步构建一个复杂对象
mybatis的初始化非常复杂,用到了大量的builder,分层构造,构建sqlsessionfactory会构建configuration对象,sqlsessionfactorybuilder会调用xmlconfigbuilder读取所有的xml和mapper.xml,然后构建configuration对象,并将该对象作为参数构建一个sqlsessionfactory对象。
在这个过程中,用到了大量的xpathparser解析,配置,语法解析,反射生成对象,存入结果缓存等步骤,这么多工作用到了大量的builder模式解决
工厂模式,创建型模式,可以根据参数的不同返回不同类的实例对象。专门创建其他类的实例对象,被创建的对象通常有相同的父类
mybatis创建sqlsession用到了工厂模式,openSession方法重载很多个,根据不同的autocommit,executor,transaction等参数输入,来构建核心的sqlsession
代理模式,给目标对象提供一个代理,并由代理对象控制原对象的引用,代理的英文名字叫做proxy,对象结构型模式,分为动态代理,静态代理
mybatis核心模式,当调用getmapper方法时,会调用mapperRegistry.getMapper,生成一个具体的代理,当调用mapper接口时,会转发给mapperproxy。invoke方法
二级缓存会造成脏读,多个namespace会有数据不一致问题,有一些鸡肋,(A,B的namespace会不一样)