fastmybatis支持原生的插件,將寫好的插件配置到mybatis配置文件中即可
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="xxxxx.MyInterceptor" />
</plugins>
</configuration>
這裏演示編寫一個分表插件
假設有4張分表,user_log0~3,記錄用戶的日誌情況
user_log0
user_log1
user_log2
user_log3
現在需要動態查詢指定到某一張表
首先生成對應的實體類,指定一張表生成,不用全部生成
/**
* 表名:user_logX
* %index% 佔位符
*/
@Table(name = "user_log%index%")
public class UserLog {
...
}
注意%index%
佔位符
Mapper不變
public interface UserLogMapper extends CrudMapper<UserLog, Long> {
}
編寫插件,新建一個類實現org.apache.ibatis.plugin.Interceptor
接口
@Intercepts({@Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class, Integer.class})})
public class UserLogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();
StatementHandler delegate = getFieldValue(handler, "delegate");
MappedStatement mappedStatement = getFieldValue(delegate, "mappedStatement");
BoundSql boundsql = handler.getBoundSql();
String sqlId = mappedStatement.getId();
if (StringUtils.startsWith(sqlId, "com.myapp.dao.UserLogMapper.")) {
String sql = boundsql.getSql();
// 獲取index
String index = String.valueOf(RequestContext.getCurrentContext().getIndex());
// 替換sql
sql = StringUtils.replace(sql, "%index%", index);
setFieldValue(boundsql, "sql", sql);
}
return invocation.proceed();
}
private <T> T getFieldValue(Object handler, String name) {
Field delegateField = ReflectionUtils.findField(handler.getClass(), name);
delegateField.setAccessible(true);
return (T) ReflectionUtils.getField(delegateField, handler);
}
private void setFieldValue(Object obj, String fieldName, Object fieldValue) {
Field field = ReflectionUtils.findField(obj.getClass(), fieldName);
if (field != null) {
try {
field.setAccessible(true);
field.set(obj, fieldValue);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
這個插件的功能很簡單,在執行sql之前替換%index%
佔位符,變成正式的index,然後執行sql
配置插件
<plugins>
<plugin interceptor="com.myapp.interceptor.UserLogInterceptor" />
</plugins>
測試用例
public class PluginTest extends BaseTests {
@Autowired
private UserLogMapper userLogMapper;
@Test
public void testInsert() {
// 指定某一張表
RequestContext.getCurrentContext().setIndex(1);
UserLog userLog = new UserLog();
userLog.setLog("insert 111");
userLogMapper.saveIgnoreNull(userLog);
}
@Test
public void testUpdate() {
RequestContext.getCurrentContext().setIndex(1);
UserLog userLog = userLogMapper.getById(1L);
userLog.setLog("update 111");
userLogMapper.updateIgnoreNull(userLog);
}
@Test
public void testGet() {
RequestContext.getCurrentContext().setIndex(1);
UserLog userLog = userLogMapper.getById(1L);
System.out.println(userLog);
}
@Test
public void testQuery() {
RequestContext.getCurrentContext().setIndex(2);
Query query = new Query();
query.eq("user_id", 3);
List<UserLog> list = userLogMapper.list(query);
System.out.println(list);
}
}
這裏使用RequestContext.getCurrentContext().setIndex(1);
指定某一張表,還可以根據userId
取模動態計算哪一張表
比如有16張分表,那麼index=userId%16
完整代碼見:fastmybatis-demo-plugin
fastmybatis是一個mybatis開發框架,其宗旨爲:簡單、快速、有效。
- 零配置快速上手
- 無需編寫xml文件即可完成CRUD操作
- 支持mysql、sqlserver、oracle、postgresql、sqlite
- 支持自定義sql,sql語句可寫在註解中或xml中
- 支持與spring-boot集成,依賴starter即可
- 支持插件編寫
- 輕量級,無侵入性,是官方mybatis的一種擴展