举个例子 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,如果这第一个执行的里面没有设置好需要的参数,后面就都获取不到。