举个例子 select * from user_{userId%16} where user_id = {userId}
dynamicTableName(String sql, String tableName) 这个方法没有传变量啊
Comment From: ahTy
求解,相同的问题,有没有办法,在线等
Comment From: wh-19970312
新的都不知道怎么使用了
Comment From: spvycf
1.config类注册 @Configuration public class MybatisPlusConfig {
public static ThreadLocal<String> TABLE_NAME = new ThreadLocal<String>();
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
HashMap<String, TableNameHandler> map = new HashMap<String, TableNameHandler>(2) {{
//动态表明的前缀
put("user", (sql, tableName) -> {
return TABLE_NAME.get();
});
}};
dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
2.业务代码中 //动态表明的后缀也就是你的‘_{userId%16}‘的值 String childTableName = "xxxxxxxx"; MybatisPlusConfig.TABLE_NAME.set(childTableName); userService.xxxxxxxxx();//会直接调用动态的表明这张表,你动态表的数据结构最好要一样。 @ahTy @wh-19970312
Comment From: qmdx
up
Comment From: wadekun
感觉示例中要在查询前将参数手动放入ThreadLocal 的方式还是不太优雅。对于有约定参数的,可以直接自己写个DynamicTableNameInterceptor 继承DynamicTableNameInnerInterceptor。重写beforeQuery,获取参数,放入ThreadLocal更好些,这样业务代码可以不用关注这个业务逻辑,直接按照约定放入参数即可,一般业务代码中参数名也是都按照约定写的,比如用户userId,商户merchantId。。
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
// super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
System.out.println(parameter);
if (Objects.nonNull(parameter) && parameter instanceof Map) {
Map params = (Map) parameter;
if (params.containsKey("userId")) {
setRequestData(String.valueOf(params.get("userId")));
}
}
if (InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) return;
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(this.changeTable(mpBs.sql()));
}
private void setRequestData(String userId) {
RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
put("userId", userId);
}});
}
这样在DynamicTableNameHandler中dynamicTableName在ThreadLocal中直接获取参数处理动态表名就可以了。
Comment From: immmp
感觉示例中要在查询前将参数手动放入ThreadLocal 的方式还是不太优雅。对于有约定参数的,可以直接自己写个DynamicTableNameInterceptor 继承DynamicTableNameInnerInterceptor。重写beforeQuery,获取参数,放入ThreadLocal更好些,这样业务代码可以不用关注这个业务逻辑,直接按照约定放入参数即可,一般业务代码中参数名也是都按照约定写的,比如用户userId,商户merchantId。。
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { // super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql); System.out.println(parameter); if (Objects.nonNull(parameter) && parameter instanceof Map) { Map params = (Map) parameter; if (params.containsKey("userId")) { setRequestData(String.valueOf(params.get("userId"))); } } if (InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) return; PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql); mpBs.sql(this.changeTable(mpBs.sql())); }
private void setRequestData(String userId) { RequestDataHelper.setRequestData(new HashMap<String, Object>() {{ put("userId", userId); }}); }这样在DynamicTableNameHandler中dynamicTableName在ThreadLocal中直接获取参数处理动态表名就可以了。 ```
beforeQuery 这个方法每次请求只执行一次,如果在你的方法前有什么拦截器执行了非业务的sql,或者一个service里面执行多个sql。 只有第一个会执行beforeQuery,如果这第一个执行的里面没有设置好需要的参数,后面就都获取不到。