一、浅析相关类
1 configuration
mybatis在启动时会取读取所有配置文件,然后加载到内存中,configuration类就是承载整个配置的类。
sqlsessionfactorybuilder调用build方法创建sqlsessionfactory,而sqlsessionfactory需要configuration配置中心提供创建的条件,在build方法中xmlconfigbuilder 将xml文件流进行初始化并parse返回configuration,返回之前需要通过parseconfiguration来真正为configuration设置信息,xpathparser负责将节点下的信息转换成xnode对象方便访问。
2 executor
executor是跟sqlsession绑定在一起的,每一个sqlsession都拥有一个新的executor对象,由configuration创建。
mybatis中所有的mapper语句的执行都是通过executor进行的,executor是mybatis的一个核心接口。
从其定义的接口方法我们可以看出,对应的增删改语句是通过executor接口的update方法进行的,查询是通过query方法进行的。
虽然executor接口的实现类有baseexecutor和cachingexecutor,而baseexecutor的子类又有simpleexecutor、reuseexecutor和batchexecutor,但baseexecutor是一个抽象类,其只实现了一些公共的封装,而把真正的核心实现都通过方法抽象出来给子类实现,如doupdate()、doquery();cachingexecutor只是在executor的基础上加入了缓存的功能,底层还是通过executor调用的,所以真正有作用的executor只有simpleexecutor、reuseexecutor和batchexecutor。
它们都是自己实现的executor核心功能,没有借助任何其它的executor实现,它们是实现不同也就注定了它们的功能也是不一样的。
3 xmlmapperbuilder
mapper文件的解析依赖于xmlconfigbuilder的mapperelement方法来解析mapper文件。
解析过程中实质是实例化一个xmlmapperbuilder对象,然后调用其parse方法,parse方法调用的configurationelement方法是真正mapper节点解析入口,包括sql解析,缓存,等。
二、单元测试
1 生成mapper实例
运用以上相关类的功能,可以直接生成mapper的类实例。
基于java的编程思想,设计一个基类:
basemappertest:
import org.apache.ibatis.binding.mapperproxyfactory; import org.apache.ibatis.builder.xml.xmlmapperbuilder; import org.apache.ibatis.datasource.unpooled.unpooleddatasource; import org.apache.ibatis.executor.executor; import org.apache.ibatis.session.configuration; import org.apache.ibatis.session.sqlsession; import org.apache.ibatis.session.transactionisolationlevel; import org.apache.ibatis.session.defaults.defaultsqlsession; import org.apache.ibatis.transaction.transaction; import org.apache.ibatis.transaction.jdbc.jdbctransaction; import org.springframework.core.env.propertysource; import org.springframework.core.io.classpathresource; import org.springframework.core.io.resource; import org.springframework.core.io.support.resourcepropertysource; import java.lang.reflect.parameterizedtype; /** * @author: lyx */ public class basemappertest<t> { /** * mapper接口类(持久层接口) */ private t mapper; /** * 数据库连接 */ private sqlsession sqlsession; /** * 执行 */ private static executor executor; /** * 配置 */ private static configuration configuration; static { try { //定义一个配置 configuration = new configuration(); configuration.setcacheenabled(false); configuration.setlazyloadingenabled(false); configuration.setaggressivelazyloading(true); configuration.setdefaultstatementtimeout(20); //读取测试环境数据库配置 propertysource propertysource = new resourcepropertysource(new classpathresource("testdb.properties")); //设置数据库链接 unpooleddatasource datasource = new unpooleddatasource(); datasource.setdriver(propertysource.getproperty("driverclassname").tostring()); datasource.seturl(propertysource.getproperty("url").tostring()); datasource.setusername(propertysource.getproperty("username").tostring()); datasource.setpassword(propertysource.getproperty("password").tostring()); //设置事务(测试设置事务不提交false) transaction transaction = new jdbctransaction(datasource, transactionisolationlevel.read_uncommitted, false); //设置执行 executor = configuration.newexecutor(transaction); } catch (exception e) { e.printstacktrace(); } } public basemappertest(string mappername) { try { //解析mapper文件 resource mapperresource = new classpathresource(mappername); xmlmapperbuilder xmlmapperbuilder = new xmlmapperbuilder(mapperresource.getinputstream(), configuration, mapperresource.tostring(), configuration.getsqlfragments()); xmlmapperbuilder.parse(); //直接实例化一个默认的sqlsession //是做单元测试,那么没必要通过sqlsessionfactorybuilder构造sqlsessionfactory,再来获取sqlsession sqlsession = new defaultsqlsession(configuration, executor, false); //将接口实例化成对象 parameterizedtype pt = (parameterizedtype) this.getclass().getgenericsuperclass(); mapperproxyfactory<t> mapperproxyfactory = new mapperproxyfactory<>((class<t>) pt.getactualtypearguments()[0]); mapper = mapperproxyfactory.newinstance(sqlsession); } catch (exception e) { e.printstacktrace(); } } /** * 返回mapper实例对象 */ public t getmapper() { return mapper; } }
配置文件:testdb.properties
driverclassname=com.mysql.cj.jdbc.driver url=jdbc:mysql://localhost:3306/demo?servertimezone=gmt&characterencoding=utf8&usessl=false&allowmultiqueries=true username=root password=root
2 demo
junit或者testng单元测试都可以实现,下面给出一个junit测试的例子
/** * @author lyx * 直接继承basemappertest,并指定待持久层测试的接口即可 */ @runwith(springrunner.class) public class baseconfigdaotest extends basemappertest<baseconfigdao> { public baseconfigdaotest() { super("mapper/basecodeconfigmapper.xml"); } @test public void selectlistbycodetest() { string code = "lyx"; list<baseconfigdto> baseconfiglist = super.getmapper().selectlistbycode(code); assert.asserttrue(baseconfiglist.size() > 0); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论