背景
在维护公司一个老项目时,出于方便的考虑,准备在项目中引入Mybatis-plus作为持久层,那么这就涉及到新老代码共存的问题。随后由于该项目是一个数据产品相关项目,有一个日志模块会记录用户的调用记录,该日志数据落库在MySQL现已存储8kw+数据,已经不堪重负了,同时产品同学期望完善一下这块的数据统计相关功能,如日流水调用量,调用趋势、商户账单相关功能,因此准备对这块日志存储进行改造,将后续日志请求落库到Clickhouse中。
改造过程
持久层采用Mybatis-plus
在用easy-code生成了mybatisplus模板信息后启动项目抛出异常如下
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
这是因为Mybatis-plus未动态生成SQL导致无绑定的statement
解决方案
-
将XML路径及其实体别名映射实体配置名称修改为适配Mybatis-plus配置
mybatis-plus.type-aliases-package=com.baidu.pojo mybatis-plus.mapper-locations=classpath:mybatis/mapper/*.xml
-
手动设置SqlSessionFactory为MybatisSqlSessionFactoryBean(该工厂类是经过Mybatis-plus增强的类,通过此类才能动态生成SQL)
@Primary @Bean(name = "mysqlSessionFactory") public SqlSessionFactory mysqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception { // MP需要使用MybatisSqlSessionFactoryBean,否则无法动态生成SQL final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/***/***/***/dal/mapper/*.xml")); MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); sessionFactory.setPlugins(mybatisPlusInterceptor); return sessionFactory.getObject(); }
同时有一点需要主要,如果主键ID需要采用主键自增方式生成ID,需要设置,默认是IdType.NONE
(若是未指定主键 ID 在调用com.baomidou.mybatisplus.core.mapper.BaseMapper#selectById 根据主键查询的话也会出现找到对应 statement 情况)
@TableId(type = IdType.INPUT)
对于需要调用分页查询时,还需设置分页插件,如上SqlSessionFactory配置设置PaginationInnerInterceptor
集成Clickhouse,同时与MySQL共存
Clickhouse数据源配置
@Configuration
@EnableConfigurationProperties(ClickHouseDruidProperties.class)
@MapperScan(basePackages = "com.***.clickhouse", sqlSessionTemplateRef = "clickHouseSqlSessionTemplate")
public class ClickHouseDataSourceConfig {
/**
* clickHouse数据源
*
* @param clickHouseDruidProperties
* @return
*/
@Bean(name = "clickHouseDataSource")
public DataSource clickHouseDataSource(ClickHouseDruidProperties clickHouseDruidProperties) {
DruidConnectionProperties defaultProperties = DruidConnectionProperties.withDefault(new DefaultConnectionProperties());
BeanUtils.copyProperties(clickHouseDruidProperties, defaultProperties, CommonUtils
.getNullPropertyNames(clickHouseDruidProperties));
DruidDataSource dataSource = DatasourceConfigUtils.createDataSource(defaultProperties);
dataSource.setName("merchantdb");
return dataSource;
}
/**
* session factory
*
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "clickHouseSqlSessionFactory")
public SqlSessionFactory clickHouseSqlSessionFactory(@Qualifier("clickHouseDataSource") DataSource dataSource) throws Exception {
final MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.CLICK_HOUSE));
bean.setPlugins(mybatisPlusInterceptor);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/***/clickhouse/*.xml"));
return bean.getObject();
}
/**
* transaction manager
*
* @param dataSource
* @return
*/
@Bean(name = "clickHouseTransactionManager")
public DataSourceTransactionManager clickHouseTransactionManager(@Qualifier("clickHouseDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* build sql session template
*
* @param sqlSessionFactory
* @return
*/
@Bean(name = "clickHouseSqlSessionTemplate")
public SqlSessionTemplate clickHouseSqlSessionTemplate(@Qualifier("clickHouseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
MySQL数据源配置
@Configuration
@MapperScan(basePackages = "com.***.dao", sqlSessionTemplateRef = "mySqlSessionTemplate")
@EnableConfigurationProperties(MySQLDruidProperties.class)
public class MybatisConfiguration {
/**
* tplinker mysql数据源
*
* @param properties
* @return
*/
@Bean(name = "mysqlDataSource")
public DataSource mysqlDataSource(MySQLDruidProperties properties) {
DruidConnectionProperties defaultProperties = DruidConnectionProperties.withDefault(new DefaultConnectionProperties());
BeanUtils.copyProperties(properties, defaultProperties, CommonUtils.getNullPropertyNames(properties));
DruidDataSource dataSource = DatasourceConfigUtils.createDataSource(defaultProperties);
dataSource.setName("merchantdb");
return dataSource;
}
@Primary
@Bean(name = "mysqlSessionFactory")
public SqlSessionFactory mysqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
// MP需要使用MybatisSqlSessionFactoryBean,否则无法动态生成SQL
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/***/mapper/*.xml"));
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
sessionFactory.setPlugins(mybatisPlusInterceptor);
return sessionFactory.getObject();
}
/**
* transaction manager
*
* @param dataSource
* @return
*/
@Bean(name = "mysqlTransactionManager")
@Primary
public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* build sql session template
*
* @param sqlSessionFactory
* @return
*/
@Bean(name = "mySqlSessionTemplate")
@Primary
public SqlSessionTemplate mySqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
标题:记一次mybatis与mybatisplus及mysql与cilickhouse共存遇到的问题
作者:JonLv
地址:http://39.108.183.139:8080/articles/2024/01/15/1705305378342.html