一、基礎知識
MyBatis 是一款優秀的持久層框架,它支援自定義 SQL、儲存過程以及高階對映。MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來配置和對映原始型別、介面為資料庫中的記錄。
官網地址:https://mybatis.org/mybatis-3/zh/index.html
本文測試和原始碼分析參考版本: Mybatis-version:3.4.1
1.1 名詞術語

名稱
|
說明
|
SqlSession
|
作為MyBatis工作的主要頂層API,表示和資料庫互動的會話,完成必要資料庫增刪改查功能 。
|
Executor
|
MyBatis執行器,是MyBatis 排程的核心,負責SQL語句的生成和查詢快取的維護。
|
StatementHandler
|
封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定引數、將Statement結果集轉換成List集合。
|
ParameterHandler
|
封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定引數、將Statement結果集轉換成List集合。
|
ResultSetHandler
|
負責將JDBC返回的ResultSet結果集物件轉換成List型別的集合
|
TypeHandler
|
負責java資料型別和jdbc資料型別之間的對映和轉換
|
MappedStatement
|
MappedStatement維護了一條<select|update|delete|insert>節點的封裝
|
SqlSource
|
負責根據使用者傳遞的parameterObject,動態地生成SQL語句,將資訊封裝到BoundSql物件中,並返回
|
BoundSql
|
表示動態生成的SQL語句以及相應的引數資訊
|
Configuration
|
MyBatis所有的配置資訊都維持在Configuration物件之中
|
MetaObject
|
MetaObject是MyBatis提供的工具類,它可以有效的獲取或修改一些重要物件的屬性。
|
1.2 流程原理分析

MyBatis執行流程節點說明
二、外掛使用
與其稱為Mybatis外掛,不如叫Mybatis攔截器,更加符合其功能定位,實際上它就是一個攔截器,應用代理模式,在方法級別上進行攔截。Mybatis3 外掛採用責任鏈模式,通過動態代理組織多個攔截器(外掛),通過這些攔截器可以改變Mybatis的預設行為(諸如SQL重寫之類的)。
責任鏈模式:責任鏈模式在面向物件程式設計裡是一種軟體設計模式,它包含了一些命令物件和一系列的處理物件。每一個處理物件決定它能處理哪些命令物件,它也知道如何將它不能處理的命令物件傳遞給該鏈中的下一個處理物件。該模式還描述了往該處理鏈的末尾新增新的處理物件的方法。
2.1 外掛原理
// 外掛宣告格式
@Intercepts({
@Signature(type =StatementHandler.class,
method="prepare" ,
args={Connection.class})})
public class MyPlugin implements Interceptor{
......
}
支援攔截的方法
- 執行器Executor(update、query、commit、rollback等方法);
- 引數處理器ParameterHandler(getParameterObject、setParameters方法);
- 結果集處理器ResultSetHandler(handleResultSets、handleOutputParameters等方法);
- SQL語法構建器StatementHandler(prepare、parameterize、batch、update、query等方法);
- @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),編寫邏輯,基於StatementHandler介面,檢視裡面對應方法,配置的引數,args為StatementHandler.query()方法的入參。參考程式碼:
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
在實際的攔截器中,可通過引數獲取物件如:
Statement statement = (Statement)invocation.getArgs()[0];
ResultHandler resultHandler = (ResultHandler)invocation.getArgs()[1];
流程說明

Mybatis的攔截器實現機制,使用的是JDK的InvocationHandler,當呼叫ParameterHandler,ResultSetHandler,StatementHandler,Executor的物件的時候,實際上使用的是Plugin這個代理類的物件,這個類實現了InvocationHandler介面。在呼叫上述被代理類的方法的時候,就會執行Plugin的invoke方法。
Plugin在invoke方法中根據@Intercepts的配置資訊(方法名,引數等)動態判斷是否需要攔截該方法,再然後使用需要攔截的方法Method封裝成Invocation,並呼叫Interceptor的proceed方法達到了攔截目標方法的結果。截器代理類物件->攔截器->目標方法,如:
Executor->Plugin->Interceptor->Invocation
Executor.Method->Plugin.invoke->Interceptor.intercept->Invocation.proceed->method.invoke
2.2 應用場景
場景
|
描述
|
分頁
|
mybatis的分頁預設是基於記憶體分頁的(查出所有,再擷取),資料量大的情況下效率較低,不過使用mybatis外掛可以改變該行為,只需要攔截StatementHandler類的prepare方法,改變要執行的SQL語句為分頁語句即可。
|
公共欄位統一賦值
|
一般業務系統都會有建立者,修改者等基礎欄位欄位,對於基礎欄位的賦值,可以在DAO層統一攔截處理,可以用mybatis外掛攔截Executor類的update方法,對相關引數進行統一賦值即可。
|
效能監控
|
對於SQL語句執行的效能監控,可以通過攔截Executor類的update, query等方法,用日誌記錄每個方法執行的時間。
|
其他
|
其實mybatis擴充套件性還是很強的,基於外掛機制,基本上可以控制SQL執行的各個階段,如執行階段,引數處理階段,語法構建階段,結果集處理階段,具體可以根據專案業務來實現對應業務邏輯。
|
三、框架使用
3.1 基於Java API模式
MyBatis 3.0版本,框架支援不使用配置xml檔案,配置可走Java API的模式,便於專案管理和維護。
基礎配置資訊
設定資料庫的連線基礎資訊,放入到application.properties檔案中。
配置專案的pom依賴檔案,具體參考專案中的配置資訊。
基礎測試物件類:


**
* @author wl
* @description 單據生命流程日誌
* @date 2019/10/9 21:06
*/
@Data
public class PayLifeLog implements Serializable { /**
* 日誌主鍵編碼
*/
private Integer logId;
/**
* 單據包編碼
*/
private String packageId;
/**
* 單據編碼
*/
private String billCode;
/**
* 節點執行結果
*/
private Byte lifeStatus;
/**
* 節點
*/
private Byte lifeState;
/**
* 備註
*/
private String markMsg;
/**
* 更新時間
*/
private LocalDateTime updatetime;
}
構建DataBaseConfiguration配置類
package com.trace.base.tool.configuration; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* 資料庫層配置類
*
* @author wl
* @date 2021-4-27
*/
@Configuration
@MapperScan(basePackages = {"com.trace.base.tool.mapper.**"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class DataBaseConfiguration {
@Value("${hikaricp.dataSource.jdbc.driverClassName}")
private String driverClassName;
@Value("${hikaricp.dataSource.url}")
private String jdbcUrl;
@Value("${hikaricp.dataSource.username}")
private String username;
@Value("${hikaricp.dataSource.password}")
private String password;
@Value("${hikaricp.dataSource.connectionTestQuery}")
private String connectionTestQuery;
@Value("${hikaricp.dataSource.connectionTimeout}")
private long connectionTimeout;
@Value("${hikaricp.dataSource.idleTimeout}")
private long idleTimeout;
@Value("${hikaricp.dataSource.maxLifetime}")
private long maxLifetime;
@Value("${hikaricp.dataSource.maximumPoolSize}")
private int maximumPoolSize;
@Value("${hikaricp.dataSource.minimumIdle}")
private int minimumIdle; /**
* 注入一個hikaricp dataSource
*/
@Bean(value = "dataSource", destroyMethod = "close")
public HikariDataSource hikariDataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setJdbcUrl(jdbcUrl);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
hikariConfig.setConnectionTestQuery(connectionTestQuery);
hikariConfig.setConnectionTimeout(connectionTimeout);
hikariConfig.setIdleTimeout(idleTimeout);
hikariConfig.setMaxLifetime(maxLifetime);
hikariConfig.setMaximumPoolSize(maximumPoolSize);
hikariConfig.setMinimumIdle(minimumIdle);
return new HikariDataSource(hikariConfig);
}
}
資料庫配置類功能:
- 讀取application.properties配置檔案的資訊,並生成一個hikariDataSource物件。
- 通過註解@MapperScan限定資料庫應用的包,支援專案中多資料來源應用。
構建Mapper介面
package com.trace.base.tool.mapper; import com.trace.base.tool.domain.base.PayLifeLog;
import com.trace.base.tool.sqlprovider.LifeLogSqlProvider;
import com.trace.base.tool.web.Page;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository; import java.util.List; /**
* @author wl
* @description 支付請求日誌-資料介面
* @date 2019/10/10 18:42
*/
@Mapper
@Repository
public interface LifeLogMapper {
/**
* 獲取批次支付失敗日誌
*
* @param billCode 單號
* @return 結果
*/
@SelectProvider(type = LifeLogSqlProvider.class, method = "getPayLifeLogByIdSql")
PayLifeLog getPayLifeLogById(@Param("billCode") String billCode);
}
設定查詢引數:
- 參考mybatis 3.4版本,帶上@param註解,保證引數傳遞正常。
- @SelectProvider註解,指定基於Java API模式,提供具體sql資訊的配置類資訊。
構建SqlProvider配置類
package com.trace.base.tool.sqlprovider; import com.trace.base.tool.domain.base.PayLifeLog;
import com.trace.base.tool.util.sql.SQL;
import com.trace.base.tool.web.Page;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param; /**
* @author wl
* @description 請求日誌sql生成器
* @date 2019/10/8 18:43
*/
public class LifeLogSqlProvider { public String getPayLifeLogByIdSql(@Param("billCode") String billCode) {
String sql = " select log_id as logId, package_id as packageId,bill_code as billCode,life_state as lifeState,life_status as lifeStatus,mark_msg as markMsg,updatetime " +
"from caiwu_pay_life_log where " +
"bill_code = #{billCode}" +
"limit 0,1";
return sql;
}
}
- 編寫一個基本類,類似xml檔案功能,生成對應執行的sql。
- sql可參考網上或者Mybatis自身的一sql生成工具類 SQL(),擴充套件開發,方便生成sql語句。
構建RestController業務控制器
package com.trace.base.tool.controller;
import com.trace.base.tool.domain.base.PayLifeLog;
import com.trace.base.tool.mapper.LifeLogMapper;
import com.trace.base.tool.web.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List; /**
* mybatis測試demo
*
* @author wl
* @date 2020-12-01
*/
@RestController
@RequestMapping("mybatis")
@Validated
public class MyBatisController { @Autowired
private LifeLogMapper lifeLogMapper; /**
* 獲取當前日誌資訊
*
* @return 返回儲存資料
*/
@GetMapping("/log")
public PayLifeLog getTraceService() {
return lifeLogMapper.getPayLifeLogById("5");
}
}
注入Mapper介面,測試獲取資料。(正式專案不應該直接在Controller裡面呼叫Mapper,需設定一個Service層,流程為:Controller->Service->Mapper)。
啟動微服務,利用Postman測試效果如下圖:

3.2 編寫慢sql監控日誌外掛
分析了sql外掛的原理,再做一個自定義外掛做測試。需求:
- 基於環境配置變數,控制該外掛是否需要啟用(如測試環境啟用,線上關閉)。
- 當sql執行時長超過1秒時,記錄執行的sql資訊,寫入到慢sql日誌中。
基礎配置資訊
設定資料庫的連線基礎資訊,放入到application.properties檔案中。
設定慢sql監控配置資訊:sql.slow.enable=true
配置專案的pom依賴檔案,具體參考專案中的配置資訊。
構建DataBaseConfiguration配置類
package com.trace.base.tool.configuration; import com.trace.base.tool.mybatis.study.StudySqlSessionFactoryBean;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; /**
* 資料庫層配置類
*
* @author wl
* @date 2021-4-27
*/
@Configuration
@MapperScan(basePackages = {"com.trace.base.tool.mapper.**"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class DataBaseConfiguration {
@Value("${hikaricp.dataSource.jdbc.driverClassName}")
private String driverClassName;
@Value("${hikaricp.dataSource.url}")
private String jdbcUrl;
@Value("${hikaricp.dataSource.username}")
private String username;
@Value("${hikaricp.dataSource.password}")
private String password;
@Value("${hikaricp.dataSource.connectionTestQuery}")
private String connectionTestQuery;
@Value("${hikaricp.dataSource.connectionTimeout}")
private long connectionTimeout;
@Value("${hikaricp.dataSource.idleTimeout}")
private long idleTimeout;
@Value("${hikaricp.dataSource.maxLifetime}")
private long maxLifetime;
@Value("${hikaricp.dataSource.maximumPoolSize}")
private int maximumPoolSize;
@Value("${hikaricp.dataSource.minimumIdle}")
private int minimumIdle; /**
* 注入一個hikaricp dataSource
*/
@Bean(value = "dataSource", destroyMethod = "close")
public HikariDataSource hikariDataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setJdbcUrl(jdbcUrl);
hikariConfig.setUsername(username);
hikariConfig.setPassword(password);
hikariConfig.setConnectionTestQuery(connectionTestQuery);
hikariConfig.setConnectionTimeout(connectionTimeout);
hikariConfig.setIdleTimeout(idleTimeout);
hikariConfig.setMaxLifetime(maxLifetime);
hikariConfig.setMaximumPoolSize(maximumPoolSize);
hikariConfig.setMinimumIdle(minimumIdle);
return new HikariDataSource(hikariConfig);
} /**
* 注入一個sqlSessionFactory
*/
@Bean(value = "sqlSessionFactory")
public StudySqlSessionFactoryBean sqlSessionFactory(HikariDataSource dataSource) {
StudySqlSessionFactoryBean sessionFactoryBean = new StudySqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean;
} /**
* 主動注入一個transactionManger,適用多資料庫事務管理器環境
*/
@Bean(value = "transactionManager")
public DataSourceTransactionManager dataSourceTransactionManager(HikariDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
資料庫配置類功能:
- 讀取application.properties配置檔案的資訊,並生成一個hikariDataSource物件。
- 自定義一個StudySqlSessionFactoryBean繼承SqlSessionFactoryBean,便於擴充套件預設的SqlSessionFactoryBean功能,並基於MyBatis Java API功能,做外掛或其他配置。
慢sql監控外掛編寫


package com.trace.base.tool.mybatis.study.plugin; import com.mysql.jdbc.PreparedStatement;
import com.trace.base.tool.logging.BaseLog;
import com.trace.base.tool.logging.Channel;
import com.trace.base.tool.logging.LevelEnum;
import com.trace.base.tool.mybatis.monitor.SlowSqlEnum;
import com.trace.base.tool.mybatis.monitor.SlowSqlLog;
import com.trace.base.tool.util.LocalDateTimeUtil;
import com.zaxxer.hikari.pool.ProxyStatement;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.logging.jdbc.PreparedStatementLogger;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.postgresql.jdbc.PgStatement; import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.Properties; /**
* 監控慢SQL外掛
*
* @author wl
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})
})
public class SlowSqlMonitorPlugin implements Interceptor {
public static final String SLOW_SQL_ENABLE = "sql.slow.enable";
private static boolean POSTGRESQL_DRIVER_AVAILABLE;
private static boolean MYSQL_DRIVER_AVAILABLE;
private static boolean HIKARICP_AVAILABLE;
private static Field DELEGATE_FIELD; static {
try {
Class.forName("org.postgresql.jdbc.PgPreparedStatement");
POSTGRESQL_DRIVER_AVAILABLE = true;
} catch (ClassNotFoundException e) {
// ignore
POSTGRESQL_DRIVER_AVAILABLE = false;
}
try {
Class.forName("com.mysql.jdbc.PreparedStatement");
MYSQL_DRIVER_AVAILABLE = true;
} catch (ClassNotFoundException e) {
// ignore
MYSQL_DRIVER_AVAILABLE = false;
}
try {
Class.forName("com.zaxxer.hikari.pool.HikariProxyPreparedStatement");
DELEGATE_FIELD = ProxyStatement.class.getDeclaredField("delegate");
DELEGATE_FIELD.setAccessible(true);
HIKARICP_AVAILABLE = true;
} catch (ClassNotFoundException | NoSuchFieldException e) {
// ignore
HIKARICP_AVAILABLE = false;
}
} @Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
try {
Object obj = invocation.proceed();
return obj;
} finally {
long end = System.currentTimeMillis();
long used = end - start;
// >= 1s
final long max = 1000L;
if (used >= max) {
try {
Object target = invocation.getTarget();
String sql = "unknown";
if (target instanceof StatementHandler) {
sql = ((StatementHandler) target).getBoundSql().getSql();
}
// 外部提前做一次猜測是否為預處理語句,只用instanceof PreparedStatement有可能沒有?,這種情況不需要執行下面邏輯
boolean mightPreparedSql = sql.contains("?");
Object statementArg = invocation.getArgs()[0];
// 可能是預處理語句才處理
if (mightPreparedSql) {
// 這裡還要區分是否為debug模式,debug模式下,生成的connection和statement都是被mybatis logger類代理
if (Proxy.isProxyClass(statementArg.getClass())) {
// 獲取到真實被代理的statement
statementArg = ((PreparedStatementLogger) Proxy.getInvocationHandler(statementArg)).getPreparedStatement();
}
// 被HikariProxyPreparedStatement代理,通過反射才能獲取到真實的PreparedStatement
if (HIKARICP_AVAILABLE && statementArg instanceof ProxyStatement) {
java.sql.PreparedStatement preparedStatement = (java.sql.PreparedStatement) DELEGATE_FIELD.get(statementArg);
// postgresql,前提是SQL為預處理語句,避免非預處理語句也執行了toString()造成拿到記憶體地址
if (POSTGRESQL_DRIVER_AVAILABLE && preparedStatement instanceof PgStatement) {
// 因為PgPreparedStatement是保護類,只能使用PgStatement轉換,實際是執行子類的toString()
sql = preparedStatement.toString();
}
// mysql
else if (MYSQL_DRIVER_AVAILABLE && preparedStatement instanceof PreparedStatement) {
sql = ((PreparedStatement) preparedStatement).asSql();
}
} }
// 記錄日誌資訊
SlowSqlLog slowSqlLog = new SlowSqlLog();
slowSqlLog.setTraceId("idnum-0001");
slowSqlLog.setType(SlowSqlEnum.DML);
slowSqlLog.setMessage("執行DML[" + sql + "]超時1秒");
slowSqlLog.setStart(LocalDateTimeUtil.formatMilliPlus8(start));
slowSqlLog.setEnd(LocalDateTimeUtil.formatMilliPlus8(end));
slowSqlLog.setUsed(used);
BaseLog<SlowSqlLog> baseLog = new BaseLog<>();
baseLog.setContext(slowSqlLog);
baseLog.setLevel(LevelEnum.WARNING.getLevel());
baseLog.setLevelName(LevelEnum.WARNING.getLevelName());
baseLog.setChannel(Channel.SYSTEM);
baseLog.setMessage("slowsql log");
baseLog.setDatetime(LocalDateTimeUtil.getMicroSecondFormattedNow());
String sqlLog=slowSqlLog.toString();
// todo 記錄日誌資訊
} catch (Throwable ex) {
// ignore
}
}
}
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) {
}
}
自定義外掛說明:
- 參考外掛的使用說明文件,指定@Intercepts,設定產生攔截的觸發條件。
- 重新實現intercept方法,監聽invocation.proceed()方法執行前後的時間,記錄sql執行的相關日誌資訊。
- 外掛中獲取的原生sql的方法,在不同的驅動,資料庫版本下,方法不一樣,僅供參考。
配置外掛
編寫完成自定義的外掛資訊後,需將外掛配置到MyBatis中,告訴它有這個外掛,才可以執行外掛功能。外掛配置可通過xml設定,或者Java API配置,基於Java配置參考如下:


package com.trace.base.tool.mybatis.study; import com.trace.base.tool.mybatis.monitor.MonitorSpringManagedTransactionFactory;
import com.trace.base.tool.mybatis.study.plugin.PagePlugin;
import com.trace.base.tool.mybatis.study.plugin.SlowSqlMonitorPlugin;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment; /**
* 自定義的sqlSessionFactoryBean
*
* @author wl
* @date 2021-3-9
*/
public class StudySqlSessionFactoryBean extends SqlSessionFactoryBean implements EnvironmentAware {
private Interceptor[] plugins;
public static Configuration CONFIGURATION;
private boolean slowSqlEnabled = false; public StudySqlSessionFactoryBean() {
this(null);
} public StudySqlSessionFactoryBean(Configuration configuration) {
super();
if (configuration == null) {
configuration = new Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
}
CONFIGURATION = configuration;
setConfiguration(configuration);
} @Override
public void setPlugins(Interceptor[] plugins) {
this.plugins = plugins;
} /**
* 真實執行設定外掛,setPlugins只用於記錄客戶端自定義的plugin,便於後續拷貝
*/
private void actualSetPlugins() {
if (slowSqlEnabled) {
// 使用自定義監控功能的事務管理器工廠類
setTransactionFactory(new MonitorSpringManagedTransactionFactory());
this.plugins = ArrayUtils.add(plugins == null ? new Interceptor[0] : plugins, new SlowSqlMonitorPlugin());
}
super.setPlugins(plugins);
} @Override
public void setEnvironment(Environment environment) {
slowSqlEnabled = environment.getProperty(SlowSqlMonitorPlugin.SLOW_SQL_ENABLE, boolean.class, true);
actualSetPlugins();
}
}
配置外掛關鍵點:
- setConfiguration只是設定Mybatis的全域性配置資訊,如設定統一的下劃線轉駝峰功能。
- 重新實現setEnvironment方法,可以獲取配置資訊,用於環境變數標識,在指定的環境下,設定外掛是否執行。
- 重新實現setPlugins方法,新增自定義的外掛。
再次啟動3.1中的測試用例,除錯程式碼,進入外掛執行函式,可檢視到自定義的外掛已經生效,效果如下:

3.3 Mybatis應用的一些思考
- 到底是xml模式設定sql好,還是Java API模式更好?
- 若基於Java API模式,MyBatis提供的動態sql工具類SQL()如何,有無侷限性?
- 若擴充套件SQL()或者自實現,有哪些方向和注意點?
- 外掛開發便於專案做監控管理,一般需要考慮哪些自定義的外掛?
- 是否存在一些開源優秀的外掛(自定義外掛可以作為參考的方向)?
- Mapper配置一些關聯查詢如何處理,如一個Mapper查詢整合其他mapper中的查詢功能?
- 多個外掛先後順序如何定義?
四、Mybatis擴充套件
Mybatis框架操作資料庫已經很優秀了,有沒有其他的ORM框架了,歡迎瞭解MybatisPlus,Spring Data Jpa 。優缺點專案開發者自己確定,也是一個不錯的方向(Mybatis Plus個人覺得裡面的部分成熟的外掛可以參考原始碼,引入到專案中)。參考文件: