mybatis單元測(cè)試過(guò)程(無(wú)需啟動(dòng)容器)
一、淺析相關(guān)類
1 Configuration
MyBatis在啟動(dòng)時(shí)會(huì)取讀取所有配置文件,然后加載到內(nèi)存中,Configuration類就是承載整個(gè)配置的類。
SqlSessionFactoryBuilder調(diào)用build方法創(chuàng)建SqlSessionFactory,而SqlSessionFactory需要Configuration配置中心提供創(chuàng)建的條件,在build方法中XMLConfigBuilder 將xml文件流進(jìn)行初始化并parse返回Configuration,返回之前需要通過(guò)parseConfiguration來(lái)真正為Configuration設(shè)置信息,XPathParser負(fù)責(zé)將節(jié)點(diǎn)下的信息轉(zhuǎn)換成XNode對(duì)象方便訪問(wèn)。
2 Executor
Executor是跟SqlSession綁定在一起的,每一個(gè)SqlSession都擁有一個(gè)新的Executor對(duì)象,由Configuration創(chuàng)建。
Mybatis中所有的Mapper語(yǔ)句的執(zhí)行都是通過(guò)Executor進(jìn)行的,Executor是Mybatis的一個(gè)核心接口。
從其定義的接口方法我們可以看出,對(duì)應(yīng)的增刪改語(yǔ)句是通過(guò)Executor接口的update方法進(jìn)行的,查詢是通過(guò)query方法進(jìn)行的。
雖然Executor接口的實(shí)現(xiàn)類有BaseExecutor和CachingExecutor,而BaseExecutor的子類又有SimpleExecutor、ReuseExecutor和BatchExecutor,但BaseExecutor是一個(gè)抽象類,其只實(shí)現(xiàn)了一些公共的封裝,而把真正的核心實(shí)現(xiàn)都通過(guò)方法抽象出來(lái)給子類實(shí)現(xiàn),如doUpdate()、doQuery();CachingExecutor只是在Executor的基礎(chǔ)上加入了緩存的功能,底層還是通過(guò)Executor調(diào)用的,所以真正有作用的Executor只有SimpleExecutor、ReuseExecutor和BatchExecutor。
它們都是自己實(shí)現(xiàn)的Executor核心功能,沒(méi)有借助任何其它的Executor實(shí)現(xiàn),它們是實(shí)現(xiàn)不同也就注定了它們的功能也是不一樣的。
3 XMLMapperBuilder
mapper文件的解析依賴于XMLConfigBuilder的mapperElement方法來(lái)解析mapper文件。
解析過(guò)程中實(shí)質(zhì)是實(shí)例化一個(gè)XMLMapperBuilder對(duì)象,然后調(diào)用其parse方法,parse方法調(diào)用的configurationElement方法是真正mapper節(jié)點(diǎn)解析入口,包括sql解析,緩存,等。
二、單元測(cè)試
1 生成mapper實(shí)例
運(yùn)用以上相關(guān)類的功能,可以直接生成mapper的類實(shí)例。
基于Java的編程思想,設(shè)計(jì)一個(gè)基類:
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; /** * 數(shù)據(jù)庫(kù)連接 */ private SqlSession sqlSession; /** * 執(zhí)行 */ private static Executor executor; /** * 配置 */ private static Configuration configuration; static { try { //定義一個(gè)配置 configuration = new Configuration(); configuration.setCacheEnabled(false); configuration.setLazyLoadingEnabled(false); configuration.setAggressiveLazyLoading(true); configuration.setDefaultStatementTimeout(20); //讀取測(cè)試環(huán)境數(shù)據(jù)庫(kù)配置 PropertySource propertySource = new ResourcePropertySource(new ClassPathResource("testdb.properties")); //設(shè)置數(shù)據(jù)庫(kù)鏈接 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()); //設(shè)置事務(wù)(測(cè)試設(shè)置事務(wù)不提交false) Transaction transaction = new JdbcTransaction(dataSource, TransactionIsolationLevel.READ_UNCOMMITTED, false); //設(shè)置執(zhí)行 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(); //直接實(shí)例化一個(gè)默認(rèn)的sqlSession //是做單元測(cè)試,那么沒(méi)必要通過(guò)SqlSessionFactoryBuilder構(gòu)造SqlSessionFactory,再來(lái)獲取SqlSession sqlSession = new DefaultSqlSession(configuration, executor, false); //將接口實(shí)例化成對(duì)象 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實(shí)例對(duì)象 */ 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單元測(cè)試都可以實(shí)現(xiàn),下面給出一個(gè)junit測(cè)試的例子
/** * @author lyx * 直接繼承BaseMapperTest,并指定待持久層測(cè)試的接口即可 */ @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); } }
???????總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springMVC之HandlerExceptionResolver使用
這篇文章主要介紹了springMVC之HandlerExceptionResolver使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11java的SimpleDateFormat線程不安全的幾種解決方案
但我們知道SimpleDateFormat是線程不安全的,處理時(shí)要特別小心,要加鎖或者不能定義為static,要在方法內(nèi)new出對(duì)象,再進(jìn)行格式化,本文就介紹了幾種方法,感興趣的可以了解一下2021-08-08Springdoc替換swagger的實(shí)現(xiàn)步驟分解
最近在spring看到的,spring要對(duì)api文檔動(dòng)手了,有些人說(shuō)swagger不好用,其實(shí)也沒(méi)那么不好用,有人說(shuō)代碼還是有點(diǎn)侵入性,這倒是真的,我剛試了springdoc可以說(shuō)還是有侵入性但是也可以沒(méi)有侵入性,這就看你對(duì)文檔有什么要求了2023-02-02Java中短路運(yùn)算符與邏輯運(yùn)算符示例詳解
這篇文章主要給大家介紹了關(guān)于Java中短路運(yùn)算符與邏輯運(yùn)算符的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01java 服務(wù)器接口快速開(kāi)發(fā)之servlet詳細(xì)教程
Servlet(Server Applet)是Java Servlet的簡(jiǎn)稱,稱為小服務(wù)程序或服務(wù)連接器,用Java編寫的服務(wù)器端程序,具有獨(dú)立于平臺(tái)和協(xié)議的特性,主要功能在于交互式地瀏覽和生成數(shù)據(jù),生成動(dòng)態(tài)Web內(nèi)容2021-06-06Java實(shí)現(xiàn)統(tǒng)計(jì)在線人數(shù)功能的方法詳解
很多人在筆試或者面試中問(wèn)到:現(xiàn)在要你實(shí)現(xiàn)一個(gè)統(tǒng)計(jì)在線人數(shù)的功能,你該怎么設(shè)計(jì)?不知道的朋友,這篇文章就來(lái)告訴你具體實(shí)現(xiàn)方法2022-08-08SpringBoot實(shí)現(xiàn)快遞物流查詢功能(快遞鳥)
本文將基于springboot2.4.0實(shí)現(xiàn)快遞物流查詢,物流信息的獲取通過(guò)快遞鳥第三方實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-10-10