Mybatis项目实时配置多个Sqlite数据源


前言

近期做了个小项目,需要在运行时实时创建或使用多个数据库(多个线程创建一对一数据库),然后对这个数据库进行操作,踩坑颇多,总结记录一下
关联版本:mybatis:3.5.9,sqlite-jdbc:3.36.0.3


一、分析

因为数据库不固定,无法使用配置文件配置,这里使用java代码中配置获取,需要新增数据源时在程序逻辑中执行多次配置即可
参考Mybatis官方文档:https://mybatis.org/mybatis-3/zh/java-api.html#sqlSessions

//1.数据源
DataSource dataSource = BaseDataTest.createBlogDataSource();
//2.事务管理器
TransactionFactory transactionFactory = new JdbcTransactionFactory();
//3.环境变量
Environment environment = new Environment("development", transactionFactory, dataSource);
//4.mybatis配置
Configuration configuration = new Configuration(environment);
configuration.setLazyLoadingEnabled(true);
configuration.setEnhancementEnabled(true);
configuration.getTypeAliasRegistry().registerAlias(Blog.class);
configuration.getTypeAliasRegistry().registerAlias(Post.class);
configuration.getTypeAliasRegistry().registerAlias(Author.class);
configuration.addMapper(BoundBlogMapper.class);
configuration.addMapper(BoundAuthorMapper.class);
//5.SqlSession工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);

二、配置步骤

1.配置数据源(DataSource)

常见spring项目相关的mybatis配置xml中,常见有以下字段:

mybatis.datasource.type = POOLED
mybatis.datasource.driver = org.sqlite.JDBC
mybatis.datasource.username = ""
mybatis.datasource.password = ""
mybatis.datasource.url = "jdbc:sqlite:...."

在java中配置,即使用datasorce后面的参数进行构建就可以了,此处要注意的是type参数不需要传入,将由后续的DataSourceFactory实现类来指定

这里我封装为一个工具类方便其他服务调用,file为指定连接的数据库文件

public class DatabaseConfigUtil {
    public static DataSource getNormalSqliteDatasource(File file) {
        Properties properties= new Properties();
        properties.put("driver", "org.sqlite.JDBC");
        properties.put("username", "");
        properties.put("password", "");
        properties.put("url", "jdbc:sqlite:"+file.getAbsolutePath());
        //有带池类型数据源/不带池类型数据源/JNDI类型数据源
        DataSourceFactory dataSourceFactory = new PooledDataSourceFactory();
        dataSourceFactory.setProperties(properties);
        return dataSourceFactory.getDataSource();
    }
}

2.配置SqlSessionFactory

/**
     * 初始化与配置数据库连接工厂
     * 参考 https://mybatis.org/mybatis-3/zh/java-api.html#sqlSessions
     * @param nowUsageDatabaseFile 当前使用的数据库文件
     */
    private void initFileDatabaseConnectFactory(File nowUsageDatabaseFile) {
        //配置数据源
        DataSource dataSource = DatabaseConfigUtil.getNormalSqliteDatasource(nowUsageDatabaseFile);
        //JDBC事务管理器
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        //mybatis环境变量,配置ID,事务管理器,数据源
        Environment environment = new Environment(nowUsageDatabaseFile.getName(), transactionFactory, dataSource);
        //设置mybatis链接配置
        Configuration configuration = new Configuration(environment);
        //启用懒加载
        configuration.setLazyLoadingEnabled(true);
        //注册表模型
        configuration.getTypeAliasRegistry().registerAlias(DanMuUserInfoModel.class);
        configuration.getTypeAliasRegistry().registerAlias(DanMuDataModel.class);
        configuration.getTypeAliasRegistry().registerAlias(DanMuFormatModel.class);
        //注册操作mapper,xml文件应跟mapper放在同一个包中,https://stackoverflow.com/questions/58522647/add-xml-mapper-to-the-configuration-of-mybatis-in-the-java-code-with-path-differ
        configuration.addMappers("com.github.cuteluobo.livedanmuarchive.mapper.danmu");
        //构建session工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //SqlSessionFactory
        nowUsageSqlSessionFactory = sqlSessionFactoryBuilder.build(configuration);
    }

注意的要点

  1. 因为新建数据源可能比较频繁,这里构建Environment的id属性我直接使用的文件名来命名,避免重复
  2. 此项目中没有通过配置文件来扫描xml的包名,如果使用xml来配置Mapper接口,需要在项目中放在resources资源目录的同名包中。
    • 例如此处我的mapper包名为com.github.cuteluobo.livedanmuarchive.mapper.danmu,那么文件存放的路径即是{poject}/resources/com/github/cuteluobo/livedanmuarchive/mapper/danmu,这样编译后的xml文件才会和对应mapper的class文件在同一个目录正常读取。项目目录
      编译后mapper目录

    • 还有另外一种方式,就是在idea中调整编译的生成目录,可以自行搜索,此处不再详细说明

3.使用

最后通过SqlSessionFactory.openSession()获取sql对话即可

try (SqlSession sqlSession = nowUsageSqlSessionFactory.openSession()) {
	    DanMuDatabaseTableMapper danMuDatabaseTableMapper = sqlSession.getMapper(DanMuDatabaseTableMapper.class);
        //do something
}

4. 其他问题

创建sqlite数据库:

不需要手动创建,只需要在配置时配置好文件路径,并创建这个文件的所有目录路径,驱动会自动生成文件。如果没有创建好文件的前置目录,抛出目录不存在的错误

自动建表与表验证:

之前建表的SQL使用了CREATE INTO {tableName} IF EXISIT {tableName} .....的判断,报错提示缺少database属性。后面换为直接从sqlite库中验证table是否存在,再创建。

以下提供两种表验证方式(Sqlite)
a.使用的验证表名SQL语句,返回符合当前名的数量

SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND tbl_name = #{tableName} 

b.或使用编程验证(返回表的字段信息)

PRAGMA table_info(#{tableName} 

后面发现a语句运行时有问题,对于新创建的数据库文件,sqlite_master表是不存在的,直接执行也会报错,所以给新创建的数据库文件加了个标识变量,新创建场景时,直接执行创建表SQL
关于b语句,在创建表后是正常的,数据库初始无表时没有进行验证,可以自行尝试


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值