一、浅析相关类
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);
}
}总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论