SpringBoot MybatisPlus 配置动态表名&多数据源

需求

业务场景: 日志、交易流水表或者其他数据量大的表,通过日期进行了水平分表,需要通过日期参数,动态的查询数据。
实现思路:利用MybatisPlus的动态表名插件DynamicTableNameInnerInterceptor ,实现Sql执行时,动态的修改表名。

实现步骤:在数据库预先创建好各年份或者月份的表之后,在配置类统一配置拦截器MybatisPlusInterceptor需要处理的动态表。

【本文业务】
对客户1001的商品资料spzl_1001

版本 3.5.2

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

SecondDataSourceConfig

打印单个数据源日志
配置拦截器
动态表名配置
配置分页,在下面配置,否则不是动态表名

@Configuration
@MapperScan(basePackages = SecondDataSourceConfig.PACKAGE, sqlSessionTemplateRef = "secondSqlSessionTemplate")
public class SecondDataSourceConfig {

    static final String PACKAGE = "com.xazy.medical.mapper.second";
    static final String MAPPER_LOCATION = "classpath*:mapper/second/*.xml";

    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.second")
    @Bean(name = "secondDataSource")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "secondSqlSessionFactory")
    public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPlugins(mybatisPlusInterceptor());
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));

        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        mybatisConfiguration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        sessionFactory.setConfiguration(mybatisConfiguration);

        return sessionFactory.getObject();
    }

    @Primary
    @Bean(name = "secondSqlSessionTemplate")
    public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory") SqlSessionFactory sessionFactory) throws Exception {
        return new SqlSessionTemplate(sessionFactory);
    }

//    @Primary
//    @Bean(name = "secondTransactionManager")
//    public DataSourceTransactionManager secondTransactionManager() {
//        return new DataSourceTransactionManager(secondDataSource());
//    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        //dynamicTableNameInnerInterceptor.setTableNameHandler(new MyTableNameHandler());//动态表名插件
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {

            if("spzl".equals(tableName) || "spkc".equals(tableName) || "spjg".equals(tableName)){
                tableName = tableName + "_001";
                log.info("动态查询表" + tableName);
            }
            return tableName;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        //放到下边位置
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

ServiceImpl 接口


/**
 * @author lyd
 * @Description: ErpSpkcService 接口实现类
 * @date 2024/05/07 14:17
 */
@Service
public class ErpSpkcServiceImpl extends ServiceImpl<ErpSpkcMapper, ErpSpkc> implements ErpSpkcService {

    @Resource
    private ErpSpkcMapper erpSpkcMapper;

    @Override
    public List<ErpSpkc> getPage(){
        Page<ErpSpkc> rowPage = new Page(1, 10);
        LambdaQueryWrapper<ErpSpkc> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ErpSpkc::getSpid, "0000000001709");
        super.baseMapper.selectPage(rowPage, queryWrapper); //分页查询
        return null;
    }

    @Override
    public List<ErpSpkc> getErpSpkcList(){
        LambdaQueryWrapper<ErpSpkc> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ErpSpkc::getSpid, "0000000001709");

        List<ErpSpkc> erpSpkcList = erpSpkcMapper.selectList(queryWrapper); //mapper查询
        return null;
    }
    
    @Override
    public List<ErpSpkc> getOneErpSpkc(){
        LambdaQueryWrapper<ErpSpkc> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ErpSpkc::getSpid, "0000000001709");
        ErpSpkc erpSpkc = this.baseMapper.selectOne(queryWrapper);
        if(erpSpkc != null){
            log.info("-----" + erpSpkc.getLasttime());
        }
        return null;
    }
}

问题

mybatis-plus添加多数据源插件和动态表名导致分页失效

日志

实体表 spkc 变为 spkc_001

2024-05-10 10:48:05.863  INFO 31392 --- [nio-8093-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-05-10 10:48:05.863  INFO 31392 --- [nio-8093-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-05-10 10:48:05.864  INFO 31392 --- [nio-8093-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@615d3061] was not registered for synchronization because synchronization is not active
2024-05-10 10:48:05.937  INFO 31392 --- [nio-8093-exec-1] c.x.m.config.SecondDataSourceConfig      : 动态查询表: spkc_001
2024-05-10 10:48:05.967  INFO 31392 --- [nio-8093-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-05-10 10:48:06.698  INFO 31392 --- [nio-8093-exec-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@654387138 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e9f079b] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM spkc_001 WHERE (spid = ?)
==> Parameters: 0000000001709(String)
<==    Columns: total
<==        Row: 1
<==      Total: 1
==>  Preparing: SELECT spid,spbh,shl,sxrq,cgy,ckid,lasttime,up_status,sjly FROM spkc_001 WHERE (spid = ?) LIMIT ?
==> Parameters: 0000000001709(String), 10(Long)
<==    Columns: spid, spbh, shl, sxrq, cgy, ckid, lasttime, up_status, sjly
<==        Row: 0000000001709, 00714, 0.0, , , , 2024/4/9 18:43:28, 0, TS039
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@615d3061]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5847749b] was not registered for synchronization because synchronization is not active
2024-05-10 10:48:07.153  INFO 31392 --- [nio-8093-exec-1] c.x.m.config.SecondDataSourceConfig      : 动态查询表: spkc_001
JDBC Connection [HikariProxyConnection@1955085493 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e9f079b] will not be managed by Spring
==>  Preparing: SELECT spid,spbh,shl,sxrq,cgy,ckid,lasttime,up_status,sjly FROM spkc_001 WHERE (spid = ?)
==> Parameters: 0000000001709(String)
<==    Columns: spid, spbh, shl, sxrq, cgy, ckid, lasttime, up_status, sjly
<==        Row: 0000000001709, 00714, 0.0, , , , 2024/4/9 18:43:28, 0, TS039
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5847749b]
2024-05-10 10:48:07.382  INFO 31392 --- [nio-8093-exec-1] c.x.m.service.impl.ErpSpkcServiceImpl    : -----ErpSpkc(spid=0000000001709, spbh=00714, shl=0.0, sxrq=, cgy=, ckid=, lasttime=2024/4/9 18:43:28, upStatus=0, sjly=TS039)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@454c8e60] was not registered for synchronization because synchronization is not active
2024-05-10 10:48:07.385  INFO 31392 --- [nio-8093-exec-1] c.x.m.config.SecondDataSourceConfig      : 动态查询表: spkc_001
JDBC Connection [HikariProxyConnection@177690205 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e9f079b] will not be managed by Spring
==>  Preparing: SELECT spid,spbh,shl,sxrq,cgy,ckid,lasttime,up_status,sjly FROM spkc_001 WHERE (spid = ?)
==> Parameters: 0000000001709(String)
<==    Columns: spid, spbh, shl, sxrq, cgy, ckid, lasttime, up_status, sjly
<==        Row: 0000000001709, 00714, 0.0, , , , 2024/4/9 18:43:28, 0, TS039
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@454c8e60]
2024-05-10 10:48:07.614  INFO 31392 --- [nio-8093-exec-1] c.x.m.service.impl.ErpSpkcServiceImpl    : -----2024/4/9 18:43:28

其他

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        //dynamicTableNameInnerInterceptor.setTableNameHandler(new MyTableNameHandler());//动态表名插件
        
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            if("spzl".equals(tableName)){
                tableName = tableName + "_001";
            }
            if("spkc".equals(tableName)){
                tableName = tableName + "_001";
            }
            if("spjg".equals(tableName)){
                tableName = tableName + "_001";
            }
            return tableName;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);

        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
&lt;think&gt;嗯,用户问的是SpringBoot集成MyBatis-Plus和OceanBase。首先,我需要确认自己对这几个技术的理解是否正确。SpringBoot是用来简化Spring应用初始搭建和开发的框架,MyBatis-Plus是对MyBatis的增强工具,提供了很多便捷的功能,比如通用的CRUD操作。OceanBase是阿里巴巴开源的分布式关系数据库,兼容MySQL协议,所以可能配置上和MySQL类似。 接下来,用户可能需要的是具体的集成步骤。首先,应该从项目搭建开始,使用Spring Initializr创建一个SpringBoot项目,添加必要的依赖,比如MyBatis-Plus和OceanBase的驱动。这里需要注意的是,OceanBase的JDBC驱动可能和MySQL的兼容,但需要确认版本是否匹配。 然后,配置数据源。在application.yml或者application.properties中配置数据库连接信息,包括URL、用户、密码。这里可能会遇到驱动类的问题,比如是使用OceanBase的驱动还是MySQL的驱动。可能需要查文档确认,如果OceanBase兼容MySQL协议,可能可以继续使用MySQL的驱动,比如com.mysql.cj.jdbc.Driver。 接下来,创建实体类和Mapper接口。MyBatis-Plus通常通过继承BaseMapper来获得基本的CRUD方法,所以用户需要创建对应的实体类,并使用注解如@TableName来指定表,@TableId来指定主键。可能需要提醒用户注意字段和数据库列的映射是否正确。 然后,可能需要配置MyBatis-Plus的分页插件或者其他插件,确保分页功能正常。这部分需要在配置类中添加@Bean,创建分页拦截器。 测试部分,用户可能需要编写一个简单的Service和Controller,进行数据库操作,比如插入和查询数据,来验证集成是否成功。这时候需要注意OceanBase的一些特性,比如是否支持事务,或者是否有特殊的配置需求。 可能遇到的问题包括驱动类找不到,连接失败,或者SQL语法不兼容。需要检查依赖是否正确,数据库服务是否启动,网络是否通畅,以及SQL语句是否符合OceanBase的语法。另外,OceanBase作为分布式数据库,可能有分库分表的情况,但MyBatis-Plus在处理这些方面可能需要额外的配置插件。 还需要考虑版本兼容性,比如SpringBoot的版本是否和MyBatis-Plus以及OceanBase的驱动兼容。可能需要查阅官方文档,确认各个组件的版本匹配。 最后,可能需要提供一些常见问题的解决方法,比如连接超时、时区设置问题,或者提示用户如何开启MyBatis-Plus的SQL日志,方便调试。 总结一下,步骤大致是:创建项目、添加依赖、配置数据源、编写实体和Mapper、配置插件、测试验证。同时需要注意OceanBase的兼容性和配置细节,确保各组件版本匹配,以及处理可能出现的连接或SQL问题。&lt;/think&gt;以下是SpringBoot集成MyBatis-Plus与OceanBase数据库的详细步骤: --- ### 一、环境准备 1. **OceanBase部署** - 安装OceanBase社区版(建议使用Docker快速部署) ```bash docker run -itd --name oceanbase-ce -p 2881:2881 -p 2883:2883 oceanbase/oceanbase-ce:latest ``` 2. **创建测试数据库** ```sql CREATE DATABASE testdb; USE testdb; CREATE TABLE user(id BIGINT PRIMARY KEY, name VARCHAR(50)); ``` --- ### 二、SpringBoot项目搭建 #### 1. 使用[start.spring.io](https://start.spring.io/)创建项目 选择依赖: - Spring Web - MyBatis Framework - MySQL Driver(因OceanBase兼容MySQL协议) #### 2. 添加额外依赖(pom.xml) ```xml &lt;!-- MyBatis-Plus --&gt; &lt;dependency&gt; &lt;groupId&gt;com.baomidou&lt;/groupId&gt; &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt; &lt;version&gt;3.5.3&lt;/version&gt; &lt;/dependency&gt; &lt;!-- OceanBase官方驱动(可选,也可继续用MySQL驱动) --&gt; &lt;dependency&gt; &lt;groupId&gt;com.oceanbase&lt;/groupId&gt; &lt;artifactId&gt;oceanbase-client&lt;/artifactId&gt; &lt;version&gt;2.4.0&lt;/version&gt; &lt;/dependency&gt; ``` --- ### 三、配置文件 `application.yml`配置: ```yaml spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver # 或com.oceanbase.jdbc.Driver url: jdbc:mysql://localhost:2883/testdb?useUnicode=true&amp;characterEncoding=utf8 username: root password: # MyBatis-Plus配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志 global-config: db-config: id-type: auto # 自增主键 ``` --- ### 四、代码实现 #### 1. 实体类 ```java @Data @TableName(&quot;user&quot;) public class User { @TableId(type = IdType.AUTO) private Long id; private String name; } ``` #### 2. Mapper接口 ```java public interface UserMapper extends BaseMapper&lt;User&gt; { } ``` #### 3. 启用Mapper扫描(启动类添加) ```java @SpringBootApplication @MapperScan(&quot;com.example.demo.mapper&quot;) public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` --- ### 五、功能验证 #### 1. 测试Service ```java @Service public class UserService { @Autowired private UserMapper userMapper; public void test() { User user = new User(); user.setName(&quot;OceanBaseUser&quot;); userMapper.insert(user); // 插入数据 System.out.println(userMapper.selectList(null)); // 查询所有 } } ``` #### 2. 调用测试 ```java @RestController public class TestController { @Autowired private UserService userService; @GetMapping(&quot;/test&quot;) public String test() { userService.test(); return &quot;执行成功&quot;; } } ``` --- ### 六、注意事项 1. **驱动选择** - MySQL驱动:兼容性更好(推荐) - OceanBase官方驱动:需确认版本匹配 2. **事务管理** ```java @Transactional // 添加事务注解 public void transactionalMethod() { // 数据库操作 } ``` 3. **分页插件配置** ```java @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } } ``` --- ### 七、常见问题排查 1. **连接失败** - 检查OceanBase服务状态 - 验证端口(默认2883)是否开放 - 确认账号权限(建议创建专用账号) 2. **时区问题** 在JDBC URL中添加参数: ```yaml url: jdbc:mysql://localhost:2883/testdb?serverTimezone=Asia/Shanghai ``` 3. **SQL兼容性** - OceanBase与MySQL存在少量语法差异 - 使用`mybatis-plus.configuration.log-impl`输出SQL调试 --- 通过以上步骤即可完成SpringBoot+MyBatis-Plus+OceanBase的集成,实际部署时需根据OceanBase集群配置调整连接参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值