日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
使用策略模式,調(diào)用參數(shù)處理器

一、前言

你這代碼寫的,咋這么軸呢!

創(chuàng)新互聯(lián)公司專注于欽州企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開發(fā),商城網(wǎng)站制作。欽州網(wǎng)站建設(shè)公司,為欽州等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站建設(shè),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

說到軸,讓我想起初中上學(xué)時(shí)老師說的話:“你那腦瓜子,咋跟手燜子似的!”

東北話手燜子就是那種冬天戴的大棉手套,棉手套里的棉花都被壓的又沉又硬的了,所以來比喻腦瓜子笨。

而寫軸代碼的大部分都是剛畢業(yè)沒多久,或者剛開始工作的碼農(nóng),畢竟經(jīng)驗(yàn)不足經(jīng)歷不多,寫出一些不太好維護(hù)的代碼也情有可原。而那些絕對(duì)多數(shù)鍛煉出來的老碼農(nóng),其實(shí)代碼的穩(wěn)定程度、設(shè)計(jì)經(jīng)驗(yàn)、縝密邏輯,都是相對(duì)來說要好很多的。當(dāng)然一部分老碼農(nóng),只是老了而已,代碼還是那個(gè)代碼!

所以企業(yè)招聘些年輕人,需要年輕的思想。但沒必要嚯嚯只是頭發(fā)沒多少的老碼農(nóng),否則誰來給你平穩(wěn)落地你那些天馬行空的想法呢!難道體驗(yàn)、穩(wěn)定、流暢,不應(yīng)該是更值得追求的,非得喜歡全是愣頭青似的代碼,寫出幾百個(gè)bug,造成大量資損和客訴,讓老板覺得很爽?

二、目標(biāo)

上一章節(jié),小傅哥帶著大家細(xì)化的 XML 語句構(gòu)建器,解耦在解析 XML 中的所需要處理的 Mapper 信息,包括;SQL、入?yún)ⅰ⒊鰠?、類型,并?duì)這些信息進(jìn)行記錄到 ParameterMapping 參數(shù)映射處理類中。那么這個(gè)一章節(jié)我們將結(jié)合這部分參數(shù)的提取,對(duì)執(zhí)行的 SQL 進(jìn)行參數(shù)的自動(dòng)化設(shè)置,而不是像我們之前那樣把參數(shù)寫成固定的,如圖 10-1 所示:

圖 10-1 硬編碼參數(shù)設(shè)置

在流程上,通過 DefaultSqlSession#selectOne 方法調(diào)用執(zhí)行器,并通過預(yù)處理語句處理器 PreparedStatementHandler 執(zhí)行參數(shù)設(shè)置和結(jié)果查詢。

那么這個(gè)流程中我們所處理的參數(shù)信息,也就是每個(gè) SQL 執(zhí)行時(shí),那些?號(hào)需要被替換的地方,目前是通過硬編碼的方式進(jìn)行處理的。而這就是本章節(jié)需要解決的問題,如果只是硬編碼完成參數(shù)設(shè)置,那么對(duì)于所有那些不同類型的參數(shù)就沒法進(jìn)行操作了。

所以本章節(jié)需要結(jié)合結(jié)合上一章節(jié)所完成的語句構(gòu)建器對(duì) SQL 參數(shù)信息的拆解,本章將會(huì)按照這些參數(shù)的解析,處理這里硬編碼為自動(dòng)化類型設(shè)置。針對(duì)不同類型的參數(shù)設(shè)置,這部分使用了什么設(shè)計(jì)模式呢?

三、設(shè)計(jì)

這里可以思考下,參數(shù)的處理也就是通常我們使用 JDBC 直接操作數(shù)據(jù)庫(kù)時(shí),所使用 ps.setXxx(i, parameter);

設(shè)置的各類參數(shù)。那么在自動(dòng)化解析 XML 中 SQL 拆分出所有的參數(shù)類型后,則應(yīng)該根據(jù)不同的參數(shù)進(jìn)行不同的類型設(shè)置,也就;Long 調(diào)用 ps.setLong、String 調(diào)用 ps.setString 所以這里需要使用策略模式,在解析 SQL 時(shí)按照不同的執(zhí)行策略,封裝進(jìn)去類型處理器(也就是是實(shí)現(xiàn) TypeHandler接口的過程)。整體設(shè)計(jì)如圖 10-2 所示:

圖 10-2 策略模式處理參數(shù)處理器

  • 其實(shí)關(guān)于參數(shù)的處理,因?yàn)橛泻芏嗟念愋?Long\String\Object\...),所以這里最重要的體現(xiàn)則是策略模式的使用。
  • 這里包括了構(gòu)建參數(shù)時(shí)根據(jù)類型,選擇對(duì)應(yīng)的策略類型處理器,填充到參數(shù)映射集合中。另外一方面是參數(shù)的使用,也就是在執(zhí)行DefaultSqlSession#selectOne 的鏈路中,包括了參數(shù)的設(shè)置,按照參數(shù)的不同類型,獲取出對(duì)應(yīng)的處理器,以及入?yún)⒅?。注意:由于入?yún)⒅悼赡苁且粋€(gè)對(duì)象中的屬性,所以這里我們用到了前面章節(jié)實(shí)現(xiàn)的反射類工具M(jìn)etaObject 進(jìn)行值的獲取,避免由于動(dòng)態(tài)的對(duì)象,沒法硬編碼獲取屬性值。

四、實(shí)現(xiàn)

1. 工程結(jié)構(gòu)

mybatis-step-09
└── src
├── main
│ └── java
│ └── cn.bugstack.mybatis
│ ├── binding
│ │ ├── MapperMethod.java
│ │ ├── MapperProxy.java
│ │ ├── MapperProxyFactory.java
│ │ └── MapperRegistry.java
│ ├── builder
│ │ ├── xml
│ │ │ ├── XMLConfigBuilder.java
│ │ │ ├── XMLMapperBuilder.java
│ │ │ └── XMLStatementBuilder.java
│ │ ├── BaseBuilder.java
│ │ ├── ParameterExpression.java
│ │ ├── SqlSourceBuilder.java
│ │ └── StaticSqlSource.java
│ ├── datasource
│ ├── executor
│ │ ├── resultset
│ │ │ └── ParameterHandler.java
│ │ ├── resultset
│ │ │ ├── DefaultResultSetHandler.java
│ │ │ └── ResultSetHandler.java
│ │ ├── statement
│ │ │ ├── BaseStatementHandler.java
│ │ │ ├── PreparedStatementHandler.java
│ │ │ ├── SimpleStatementHandler.java
│ │ │ └── StatementHandler.java
│ │ ├── BaseExecutor.java
│ │ ├── Executor.java
│ │ └── SimpleExecutor.java
│ ├── io
│ ├── mapping
│ │ ├── BoundSql.java
│ │ ├── Environment.java
│ │ ├── MappedStatement.java
│ │ ├── ParameterMapping.java
│ │ ├── SqlCommandType.java
│ │ └── SqlSource.java
│ ├── parsing
│ ├── reflection
│ ├── scripting
│ │ ├── defaults
│ │ │ └── DefaultParameterHandler.java
│ │ ├── xmltags
│ │ │ ├── DynamicContext.java
│ │ │ ├── MixedSqlNode.java
│ │ │ ├── SqlNode.java
│ │ │ ├── StaticTextSqlNode.java
│ │ │ ├── XMLLanguageDriver.java
│ │ │ └── XMLScriptBuilder.java
│ │ ├── LanguageDriver.java
│ │ └── LanguageDriverRegistry.java
│ ├── session
│ │ ├── defaults
│ │ │ ├── DefaultSqlSession.java
│ │ │ └── DefaultSqlSessionFactory.java
│ │ ├── Configuration.java
│ │ ├── ResultHandler.java
│ │ ├── SqlSession.java
│ │ ├── SqlSessionFactory.java
│ │ ├── SqlSessionFactoryBuilder.java
│ │ └── TransactionIsolationLevel.java
│ ├── transaction
│ └── type
│ ├── BaseTypeHandler.java
│ ├── JdbcType.java
│ ├── LongTypeHandler.java
│ ├── StringTypeHandler.java
│ ├── TypeAliasRegistry.java
│ ├── TypeHandler.java
│ └── TypeHandlerRegistry.java
└── test
├── java
│ └── cn.bugstack.mybatis.test.dao
│ ├── dao
│ │ └── IUserDao.java
│ ├── po
│ │ └── User.java
│ └── ApiTest.java
└── resources
├── mapper
│ └──User_Mapper.xml
└── mybatis-config-datasource.xml

使用策略模式,處理參數(shù)處理器核心類關(guān)系,如圖 10-3 所示:

圖 10-3 使用策略模式,處理參數(shù)處理器核心類關(guān)系

核心處理主要分為三塊;類型處理、參數(shù)設(shè)置、參數(shù)使用;

  • 以定義 TypeHandler 類型處理器策略接口,實(shí)現(xiàn)不同的處理策略,包括;Long、String、Integer 等。這里我們先只實(shí)現(xiàn)2種類型,讀者在學(xué)習(xí)過程中,可以按照這個(gè)結(jié)構(gòu)來添加其他類型。
  • 類型策略處理器實(shí)現(xiàn)完成后,需要注冊(cè)到處理器注冊(cè)機(jī)中,后續(xù)其他模塊參數(shù)的設(shè)置還是使用都是從 Configuration 中獲取到 TypeHandlerRegistry 進(jìn)行使用。
  • 那么有了這樣的策略處理器以后,在進(jìn)行操作解析 SQL 的時(shí)候,就可以按照不同的類型把對(duì)應(yīng)的策略處理器設(shè)置到BoundSql#parameterMappings 參數(shù)里,后續(xù)使用也是從這里進(jìn)行獲取。

2. 入?yún)?shù)校準(zhǔn)

這里我們要先解決一個(gè)小問題,不知道讀者在我們所實(shí)現(xiàn)的源碼中,是否注意到這樣一個(gè)參數(shù)的傳遞,如圖 10-4:

圖 10-4 參數(shù)設(shè)置時(shí)入?yún)@取

  • 這里的參數(shù)傳遞后,需要獲取第0個(gè)參數(shù),而且是硬編碼固定的。這是為什么呢?這個(gè)第0個(gè)參數(shù)是哪來的,我們接口里面調(diào)用的方法,參數(shù)不是一個(gè)嗎?就像:User queryUserInfoById(Long id);
  • 其實(shí)這個(gè)參數(shù)來自于映射器代理類 MapperProxy#invoke 中,因?yàn)?invoke 反射調(diào)用的方法,入?yún)⒅惺?Object[] args,所以這個(gè)參數(shù)被傳遞到后續(xù)的參數(shù)設(shè)置中。而我們的 DAO 測(cè)試類是一個(gè)已知的固定參數(shù),所以后面硬編碼了獲取了第0個(gè)參數(shù)。

JDK 反射調(diào)用方法操作固定方法入?yún)?/p>

  • 那么結(jié)合這樣的問題,我們則需要根據(jù)方法的信息,給方法做簽名操作,以便于轉(zhuǎn)換入?yún)⑿畔榉椒ǖ男畔?。比如?shù)組轉(zhuǎn)換為對(duì)應(yīng)的對(duì)象。

源碼詳見:cn.bugstack.mybatis.binding.MapperMethod

public class MapperMethod {

public Object execute(SqlSession sqlSession, Object[] args) {
Object result = null;
switch (command.getType()) {
case SELECT:
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
break;
default:
throw new RuntimeException("Unknown execution method for: " + command.getName());
}
return result;
}

/**
* 方法簽名
*/
public static class MethodSignature {

public Object convertArgsToSqlCommandParam(Object[] args) {
final int paramCount = params.size();
if (args == null || paramCount == 0) {
// 如果沒參數(shù)
return null;
} else if (paramCount == 1) {
return args[params.keySet().iterator().next().intValue()];
} else {
// 否則,返回一個(gè)ParamMap,修改參數(shù)名,參數(shù)名就是其位置
final Map param = new ParamMap();
int i = 0;
for (Map.Entry entry : params.entrySet()) {
// 1.先加一個(gè)#{0},#{1},#{2}...參數(shù)
param.put(entry.getValue(), args[entry.getKey().intValue()]);
// ...
}
return param;
}
}

}
}

在映射器方法中 MapperMethod#execute 將原來的直接將參數(shù) args 傳遞給 SqlSession#selectOne 方法,調(diào)整為轉(zhuǎn)換后再傳遞對(duì)象。

其實(shí)這里的轉(zhuǎn)換操作就是來自于 Method#getParameterTypes 對(duì)參數(shù)的獲取和處理,與 args 進(jìn)行比對(duì)。如果是單個(gè)參數(shù),則直接返回參數(shù)

Tree 樹結(jié)構(gòu)下的對(duì)應(yīng)節(jié)點(diǎn)值。非單個(gè)類型,則需要進(jìn)行循環(huán)處理,這樣轉(zhuǎn)換后的參數(shù)才能被直接使用。

3. 參數(shù)策略處理器

在 Mybatis 的源碼包中,有一個(gè) type 包,這個(gè)包下所提供的就是一套參數(shù)的處理策略集合。它通過定義類型處理器接口、由抽象模板實(shí)現(xiàn)并定義標(biāo)準(zhǔn)流程,到提取抽象方法交給子類實(shí)現(xiàn),這些子類就是各個(gè)類型處理器的具體實(shí)現(xiàn)。

3.1 策略接口

源碼詳見:cn.bugstack.mybatis.type.TypeHandler

public interface TypeHandler {

/**
* 設(shè)置參數(shù)
*/
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

}
  • 首先定義一個(gè)類型處理器的接口,這和我們?cè)谌粘5臉I(yè)務(wù)開發(fā)中是類似的,就像如果是發(fā)貨商品,則定義一個(gè)統(tǒng)一標(biāo)準(zhǔn)接口,之后根據(jù)這個(gè)接口實(shí)現(xiàn)出不同的發(fā)貨策略。
  • 這里設(shè)置參數(shù)也是一樣,所有不同類型的參數(shù),都可以被提取出來這些標(biāo)準(zhǔn)的參數(shù)字段和異常,后續(xù)的子類按照這個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn)即可。Mybatis 源碼中有30+個(gè)類型處理。

3.2 模板模式

源碼詳見:cn.bugstack.mybatis.type.BaseTypeHandler

public abstract class BaseTypeHandler implements TypeHandler {

@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
// 定義抽象方法,由子類實(shí)現(xiàn)不同類型的屬性設(shè)置
setNonNullParameter(ps, i, parameter, jdbcType);
}

protected abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

}
  • 通過抽象基類的流程模板定義,便于一些參數(shù)的判斷和處理。不過目前我們還不需要那么多的流程校驗(yàn),所以這里只是定義和調(diào)用了一個(gè)最基本的抽象方法 setNonNullParameter。
  • 不過有一個(gè)這樣的結(jié)構(gòu),可以讓大家更加清楚整個(gè) Mybatis 源碼的框架,便于后續(xù)閱讀或者擴(kuò)展此部分源碼的時(shí)候,有一個(gè)框架結(jié)構(gòu)的認(rèn)知。

3.3 子類實(shí)現(xiàn)

源碼詳見:cn.bugstack.mybatis.type.*

/**
* @description Long類型處理器
*/
public class LongTypeHandler extends BaseTypeHandler {

@Override
protected void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
ps.setLong(i, parameter);
}

}

/**
* @description String類型處理器
*/
public class StringTypeHandler extends BaseTypeHandler{

@Override
protected void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter);
}

}

這里的接口實(shí)現(xiàn)舉了個(gè)例子,分別是;LongTypeHandler、StringTypeHandler,在 Mybatis 源碼中還有很多其他類型,這里我們暫時(shí)不需要實(shí)現(xiàn)那么多,只要清楚這個(gè)處理過程和編碼方式即可。大家在學(xué)習(xí)中,可以嘗試再添加幾個(gè)其他類型,用于學(xué)習(xí)驗(yàn)證。

3.4 類型注冊(cè)機(jī)

類型處理器注冊(cè)機(jī) TypeHandlerRegistry 是我們前面章節(jié)實(shí)現(xiàn)的,這里只需要在這個(gè)類結(jié)構(gòu)下,注冊(cè)新的類型就可以了。

源碼詳見:cn.bugstack.mybatis.type.TypeHandlerRegistry

public final class TypeHandlerRegistry {

private final Map> JDBC_TYPE_HANDLER_MAP = new EnumMap<>(JdbcType.class);
private final Map>> TYPE_HANDLER_MAP = new HashMap<>();
private final Map, TypeHandler> ALL_TYPE_HANDLERS_MAP = new HashMap<>();

public TypeHandlerRegistry() {
register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());

register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
}

//...
}
  • 這里在構(gòu)造函數(shù)中,新增加了 LongTypeHandler、StringTypeHandler 兩種類型的注冊(cè)器。
  • 同時(shí)可以注意到,無論是對(duì)象類型,還是基本類型,都是一個(gè)類型處理器。只不過在注冊(cè)的時(shí)候多注冊(cè)了一個(gè)。這種操作方式和我們平常的業(yè)務(wù)開發(fā)中,也是一樣的。一種是多注冊(cè),另外一種是判斷處理。

4. 參數(shù)構(gòu)建

相對(duì)于前面章節(jié)所完成的內(nèi)容,這個(gè)章節(jié)需要對(duì) SqlSourceBuilder 源碼構(gòu)建器中,創(chuàng)建參數(shù)映射 ParameterMapping 需要添加參數(shù)處理器的內(nèi)容。因?yàn)橹挥羞@樣才能方便的從參數(shù)映射中獲取到對(duì)應(yīng)類型的處理器進(jìn)行使用。

那么就需要完善 ParameterMapping 添加 TypeHandler 屬性信息,以及在 ParameterMappingTokenHandler#buildParameterMapping

處理參數(shù)映射時(shí),構(gòu)建出參數(shù)的映射。這一部分是在上一章節(jié)的實(shí)現(xiàn)過程中,細(xì)化的完善部分,如圖 10-6:

圖 10-6 構(gòu)建參數(shù)映射

那么結(jié)合上一章節(jié),這里我們開始擴(kuò)展出類型的設(shè)置。同時(shí)注意 MetaClass 反射工具類的使用。

源碼詳見:cn.bugstack.mybatis.builder.SqlSourceBuilder

// 構(gòu)建參數(shù)映射
private ParameterMapping buildParameterMapping(String content) {
// 先解析參數(shù)映射,就是轉(zhuǎn)化成一個(gè) HashMap | #{favouriteSection,jdbcType=VARCHAR}
Map propertiesMap = new ParameterExpression(content);
String property = propertiesMap.get("property");
Class propertyType;
if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
propertyType = parameterType;
} else if (property != null) {
MetaClass metaClass = MetaClass.forClass(parameterType);
if (metaClass.hasGetter(property)) {
propertyType = metaClass.getGetterType(property);
} else {
propertyType = Object.class;
}
} else {
propertyType = Object.class;
}
logger.info("構(gòu)建參數(shù)映射 property:{} propertyType:{}", property, propertyType);
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
return builder.build();
}
  • 這一部分就是對(duì)參數(shù)的細(xì)化處理,構(gòu)建出參數(shù)的映射關(guān)系,首先是 if 判斷對(duì)應(yīng)的參數(shù)類型是否在 TypeHandlerRegistry 注冊(cè)器中,如果不在則拆解對(duì)象,按屬性進(jìn)行獲取 propertyType 的操作。
  • 這一塊也用到了 MetaClass 反射工具類的使用,它的存在可以讓我們更加方便的處理,否則還需要要再寫反射類進(jìn)行獲取對(duì)象屬性操作。

5. 參數(shù)使用

參數(shù)構(gòu)建完成后,就可以在 DefaultSqlSession#selectOne 調(diào)用時(shí)設(shè)置參數(shù)使用了。那么這里的鏈路關(guān)系;Executor#query - > SimpleExecutor#doQuery -> StatementHandler#parameterize -> PreparedStatementHandler#parameterize -> ParameterHandler#setParameters 到了 ParameterHandler#setParameters 就可以看到了根據(jù)參數(shù)的不同處理器循環(huán)設(shè)置參數(shù)。

源碼詳見:cn.bugstack.mybatis.scripting.defaults.DefaultParameterHandler

public class DefaultParameterHandler implements ParameterHandler {

@Override
public void setParameters(PreparedStatement ps) throws SQLException {
List parameterMappings = boundSql.getParameterMappings();
if (null != parameterMappings) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
String propertyName = parameterMapping.getProperty();
Object value;
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
// 通過 MetaObject.getValue 反射取得值設(shè)進(jìn)去
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
JdbcType jdbcType = parameterMapping.getJdbcType();

// 設(shè)置參數(shù)
logger.info("根據(jù)每個(gè)ParameterMapping中的TypeHandler設(shè)置對(duì)應(yīng)的參數(shù)信息 value:{}", JSON.toJSONString(value));
TypeHandler typeHandler = parameterMapping.getTypeHandler();
typeHandler.setParameter(ps, i + 1, value, jdbcType);
}
}
}

}
  • 每一個(gè)循環(huán)的參數(shù)設(shè)置,都是從 BoundSql 中獲取 ParameterMapping 集合進(jìn)行循環(huán)操作,而這個(gè)集合參數(shù)就是我們前面ParameterMappingTokenHandler#buildParameterMapping 構(gòu)建參數(shù)映射時(shí)處理的。
  • 設(shè)置參數(shù)時(shí)根據(jù)參數(shù)的 parameterObject 入?yún)⒌男畔?,判斷是否基本類型,如果不是則從對(duì)象中進(jìn)行拆解獲取(也就是一個(gè)對(duì)象A中包括屬性b),處理完成后就可以準(zhǔn)確拿到對(duì)應(yīng)的入?yún)⒅盗?。因?yàn)樵谟成淦鞣椒?MapperMethod 中已經(jīng)處理了一遍方法簽名,所以這里的入?yún)⒕透奖闶褂昧恕?/li>
  • 基本信息獲取完成后,則根據(jù)參數(shù)類型獲取到對(duì)應(yīng)的 TypeHandler 類型處理器,也就是找到 LongTypeHandler、StringTypeHandler 等,確定找到以后,則可以進(jìn)行對(duì)應(yīng)的參數(shù)設(shè)置了 typeHandler.setParameter(ps, i + 1, value, jdbcType) 通過這樣的方式把我們之前硬編碼的操作進(jìn)行解耦。

五、測(cè)試

1. 事先準(zhǔn)備

1.1 創(chuàng)建庫(kù)表

創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)名稱為 mybatis 并在庫(kù)中創(chuàng)建表 user 以及添加測(cè)試數(shù)據(jù),如下:

USER
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
userId VARCHAR(9) COMMENT '用戶ID',
userHead VARCHAR(16) COMMENT '用戶頭像',
createTime TIMESTAMP NULL COMMENT '創(chuàng)建時(shí)間',
updateTime TIMESTAMP NULL COMMENT '更新時(shí)間',
userName VARCHAR(64),
PRIMARY KEY (id)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into user (id, userId, userHead, createTime, updateTime, userName) values (1, '10001', '1_04', '2022-04-13 00:00:00', '2022-04-13 00:00:00', '小傅哥');

1.2 配置數(shù)據(jù)源











  • 通過 mybatis-config-datasource.xml 配置數(shù)據(jù)源信息,包括:driver、url、username、password。
  • 在這里 dataSource 可以按需配置成 DRUID、UNPOOLED 和 POOLED 進(jìn)行測(cè)試驗(yàn)證。

1.3 配置Mapper



  • 這部分暫時(shí)不需要調(diào)整,目前還只是一個(gè)入?yún)⒌念愋偷膮?shù),后續(xù)我們?nèi)客晟七@部分內(nèi)容以后,則再提供更多的其他參數(shù)進(jìn)行驗(yàn)證。

2. 單元測(cè)試

源碼詳見:cn.bugstack.mybatis.test.ApiTest

@Before
public void init() throws IOException {
// 1. 從SqlSessionFactory中獲取SqlSession
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config-datasource.xml"));
sqlSession = sqlSessionFactory.openSession();
}

因?yàn)榻酉聛砦覀冃枰?yàn)證兩種不同入?yún)⒌膯卧獪y(cè)試,分別來測(cè)試基本類型參數(shù)和對(duì)象類型參數(shù)。

2.1 基本類型參數(shù)

@Test
public void test_queryUserInfoById() {
// 1. 獲取映射器對(duì)象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
// 2. 測(cè)試驗(yàn)證:基本參數(shù)
User user = userDao.queryUserInfoById(1L);
logger.info("測(cè)試結(jié)果:{}", JSON.toJSONString(user));
}

07:40:08.531 [main] INFO  c.b.mybatis.builder.SqlSourceBuilder - 構(gòu)建參數(shù)映射 property:id propertyType:class java.lang.Long
07:40:08.598 [main] INFO c.b.m.s.defaults.DefaultSqlSession - 執(zhí)行查詢 statement:cn.bugstack.mybatis.test.dao.IUserDao.queryUserInfoById parameter:1
07:40:08.875 [main] INFO c.b.m.d.pooled.PooledDataSource - Created connection 183284570.
07:40:08.894 [main] INFO c.b.m.s.d.DefaultParameterHandler - 根據(jù)每個(gè)ParameterMapping中的TypeHandler設(shè)置對(duì)應(yīng)的參數(shù)信息 value:1
07:40:08.961
分享標(biāo)題:使用策略模式,調(diào)用參數(shù)處理器
文章起源:http://m.5511xx.com/article/djcedsg.html