mybatis plus 多数据源配置 以及方言自定义
mybatis plus 多数据源配置以及自定义方言
因为项目需要从HIS系统取医疗数据,我们的HIS系统是Caché,mybatis plus暂未收录。我们需要多数据源配置,以及分页涉及到的方言自定义。
架构使用最流行的架构 RuoYi--Vue-Plus(只是用的若依的前端 后端支持集群分布式,后端技术栈都是当先最流行的。)RuoYi-Vue-Plus: 后台管理系统 重写RuoYi-Vue所有功能 集成 Sa-Token+Mybatis-Plus+Jackson+Xxl-Job+SpringDoc+Hutool+OSS 定期同步
将项目中的关键代码贴到这里以便记录。
application-dev.yml数据库url配置
master:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://XXX.XX.XX.XX:3306/MYSQL1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: XXXX
password: XXXXX
# 从库数据源
slave:
lazy: true
driverClassName: com.intersys.jdbc.CacheDriver
url: jdbc:Cache://XX.XX.X.XX:1972/dhc-app
username: XXXXX
password: XXXX
# 从库数据源
third:
lazy: true
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.XX.XX.XX:3306/MYSQL2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: XXX
password: XXXX@XXX
从库调用service(支持具体方法上写@DS,因为我个人感觉太乱,所以从库采用直接对应自己的service,在类上写@DS)代码如下:
@DS("slave")
@RequiredArgsConstructor
@Service
//@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public class InsuTarcontrastServiceImpl implements InsuTarcontrastService {
final InsuTarcontrastMapper baseMapper;
@Override
public TableDataInfo<InsuTarcontrastVo> queryPageList(InsuTarcontrastBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<InsuTarcontrast> lqw = buildQueryWrapper(bo);
Page<InsuTarcontrastVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
private LambdaQueryWrapper<InsuTarcontrast> buildQueryWrapper(InsuTarcontrastBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<InsuTarcontrast> lqw = Wrappers.lambdaQuery();
// lqw.eq(bo.getVdays() != null, BonusBaseVdays::getVdays, bo.getVdays());
// lqw.le(StringUtils.isNotBlank(bo.getStartyrmon()), BonusBaseVdays::getStartyrmon, bo.getStartyrmon());
// lqw.ge(StringUtils.isNotBlank(bo.getStartyrmon()), BonusBaseVdays::getEndyrmon, bo.getStartyrmon());
// lqw.eq(StringUtils.isNotBlank(bo.getType()), BonusBaseVdays::getType, bo.getType());
// lqw.eq(StringUtils.isNotBlank(bo.getFlag()), BonusBaseVdays::getFlag, bo.getFlag());
return lqw;
}
}
注意:加上@Transactional是因为在调mysql数据库的service 再调用Caché数据库,会报异常,具体异常忘记了,用到的小伙伴可以注释掉这句话试试。
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
这里就实现了多数据源配置。但因为直接使用分页的话,由于mybatis-plus暂未收录Caché数据库的方言,所以我们若用到分页,需要实现自定义方言。看了Caché的文档,分页需要行号,有两种方式可以获取行号,根据分页的特性,我选择%vid.方言CacheDialect.java如下:
public class CacheDialect implements IDialect {
@Override
public DialectModel buildPaginationSql(String originalSql, long offset, long limit) {
long firstParam = offset + 1;
long secondParam = offset + limit;
String sql = "SELECT %VID,* FROM " +
"("+originalSql+")" +
" WHERE %VID BETWEEN " + FIRST_MARK + " AND " + SECOND_MARK;
return new DialectModel(sql, firstParam, secondParam).setConsumerChain();
}
}
接下来问题,怎么让方言起作用,看过mybatis plus的issue,已经给出的回复 重写某个方法,那么只能是重写拦截器的某个方法,自然想到PaginationInnerInterceptor的findIDialect方法,代码如下:
public class MyPaginationInnerInterceptor extends PaginationInnerInterceptor {
@Override
protected IDialect findIDialect(Executor executor) {
DbType dbType = JdbcUtils.getDbType(executor);;
if("other".equals(dbType.getDb()))
{
super.setDialect(new CacheDialect());
return super.getDialect();
}
return DialectFactory.getDialect(JdbcUtils.getDbType(executor));
}
}
如果就一个数据库方言没有在mybatis plus里,那么我就可以直接
if("other".equals(dbType.getDb())),假如比较倒霉有多个数据库方言需要自定义,那么只能通过拿到链接url 通过url分析了,这种作者没有去验证,只能说理论上支持。Connection conn = executor.getTransaction().getConnection();
最后配置拦截器地方改造MybatisPlusConfig.java:
/** * 分页插件,自动识别数据库类型 */ public PaginationInnerInterceptor paginationInnerInterceptor() { //改造分页拦截器 适配Caché数据库 MyPaginationInnerInterceptor paginationInnerInterceptor = new MyPaginationInnerInterceptor(); // 设置最大单页限制数量,默认 500 条,-1 不受限制 paginationInnerInterceptor.setMaxLimit(-1L); // 分页合理化 paginationInnerInterceptor.setOverflow(true); return paginationInnerInterceptor; }
Caché库
mysql库
那么想要的功能 实现,分页实现后不用把Caché数据同步到mysql了,我们可以直接调库了。
因为Caché的sql语法支持-> 写法 例如
SELECT TP_TARI_ParRef->TARI_Code AS tariCode,TP_TARI_ParRef->TARI_Desc AS tariDesc 这种写法如果正常情况下mybatis plus会报错。mapper增加注解
@InterceptorIgnore(tenantLine = "true")
@InterceptorIgnore(tenantLine = "true")
public interface DhcTaritempriceMapper extends BaseMapperPlus<DhcTaritempriceMapper, DhcTaritemprice, DhcTaritempriceVo> {
}
若果不想写@select,自己定义sql,需要在model里写注解
@TableField("TP_TARI_ParRef->TARI_UOM->CTUOM_Desc")
例子代码如下:
/**
* 收费项代码
*/
@TableField("TP_TARI_ParRef->TARI_Code")
private String tariCode;
/**
* 收费项目名称
*/
@TableField("TP_TARI_ParRef->TARI_Desc")
private String tariDesc;
/**
* 单位
*/
@TableField("TP_TARI_ParRef->TARI_UOM->CTUOM_Desc")
private String ctuomDesc;
最终idea控制台打印sql
SELECT %VID,* FROM (SELECT TP_TARI_ParRef->TARI_Code AS tariCode,TP_TARI_ParRef->TARI_Desc AS tariDesc,TP_TARI_ParRef->TARI_UOM->CTUOM_Desc AS ctuomDesc,tp_price FROM dhc_taritemprice) WHERE %VID BETWEEN 1 AND 10
更多推荐
所有评论(0)