因为项目需要从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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐