文章目录
- 前言
- 一、分析
- 二、配置步骤
- 1.配置数据源(DataSource)
- 2.配置SqlSessionFactory
- 3.使用
- 4. 其他问题
- 创建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);
}
注意的要点
- 因为新建数据源可能比较频繁,这里构建
Environment
的id属性我直接使用的文件名来命名,避免重复 - 此项目中没有通过配置文件来扫描xml的包名,如果使用xml来配置Mapper接口,需要在项目中放在
resources
资源目录的同名包中。
- 例如此处我的mapper包名为
com.github.cuteluobo.livedanmuarchive.mapper.danmu
,那么文件存放的路径即是{poject}/resources/com/github/cuteluobo/livedanmuarchive/mapper/danmu
,这样编译后的xml文件才会和对应mapper的class文件在同一个目录正常读取。 - 还有另外一种方式,就是在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语句,在创建表后是正常的,数据库初始无表时没有进行验证,可以自行尝试