129 lines
5.4 KiB
Java
129 lines
5.4 KiB
Java
package quant.rich.emoney.config;
|
|
|
|
import java.io.File;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import javax.sql.DataSource;
|
|
|
|
import org.apache.ibatis.session.SqlSessionFactory;
|
|
import org.mybatis.spring.SqlSessionTemplate;
|
|
import org.mybatis.spring.annotation.MapperScan;
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.context.annotation.Configuration;
|
|
import org.springframework.core.io.ClassPathResource;
|
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
|
|
|
import com.baomidou.mybatisplus.annotation.DbType;
|
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
|
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
|
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
|
import com.zaxxer.hikari.HikariDataSource;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import quant.rich.emoney.EmoneyAutoApplication;
|
|
|
|
@Slf4j
|
|
@Configuration
|
|
@MapperScan(basePackages = "quant.rich.emoney.mapper.sqlite", sqlSessionTemplateRef = "sqliteSqlSessionTemplate")
|
|
public class SqliteMybatisConfig {
|
|
|
|
private static final String RESOURCE_PATH = "database.db";
|
|
|
|
public static final String SQLITE_TRANSACTION_MANAGER = "sqliteTransactionManager";
|
|
|
|
/**
|
|
* 配置数据库连接
|
|
* <ul>
|
|
* <li>如果非打包状态,则直接选取当前项目内数据库位置</li>
|
|
* <li>如果打包状态,以 JDBC 链接位置为主,如果位置不存在则覆盖</li>
|
|
* </ul>
|
|
* @param dataSource
|
|
*/
|
|
public void initSQLiteLocation(DataSource dataSource) {
|
|
// 指定 sqlite 路径
|
|
if (dataSource instanceof HikariDataSource hikariDataSource) {
|
|
|
|
String filePath = hikariDataSource.getJdbcUrl();
|
|
if (filePath == null || !filePath.startsWith("jdbc:sqlite:")) {
|
|
log.warn(
|
|
"无法在 SQLite HikariDataSource 中找到合法 SQLite JDBC url, "
|
|
+ "数据库可能会加载失败。合法的 url 需在 application.yml(properties) "
|
|
+ "中配置,以 jdbc:sqlite: 开头。当前获取到的 jdbc-url: {}", filePath);
|
|
return;
|
|
}
|
|
filePath = filePath.substring("jdbc:sqlite:".length()).trim();
|
|
|
|
ClassPathResource original = new ClassPathResource(RESOURCE_PATH);
|
|
if (!original.exists()) {
|
|
log.warn("未找到 SQLite 资源: {}", RESOURCE_PATH);
|
|
return;
|
|
}
|
|
String protocol = EmoneyAutoApplication.class.getProtectionDomain().getCodeSource().getLocation().getProtocol();
|
|
boolean isJar = "jar".equals(protocol);
|
|
|
|
if (isJar) {
|
|
// 复制到外部 yml 指定路径,已存在则不复制
|
|
File dest = new File(filePath), parentDir = dest.getParentFile();
|
|
String destAbsolutePath = dest.getAbsolutePath();
|
|
if (!parentDir.exists() && !parentDir.mkdirs()) {
|
|
log.warn("无法创建放置 SQLite 文件的目录: {}", parentDir.getAbsolutePath());
|
|
return;
|
|
}
|
|
|
|
if (dest.exists()) {
|
|
// 已存在
|
|
log.warn("目标资源 {} 已存在,忽略", destAbsolutePath);
|
|
return;
|
|
}
|
|
|
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(RESOURCE_PATH)) {
|
|
if (in == null) {
|
|
log.warn("无法读取 SQLite 资源: {}", RESOURCE_PATH);
|
|
return;
|
|
}
|
|
Files.copy(in, dest.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
|
log.info("SQLite 数据库文件已复制至:{}", destAbsolutePath);
|
|
} catch (Exception e) {
|
|
log.warn("复制 SQLite 数据库文件失败", e);
|
|
}
|
|
}
|
|
else {
|
|
// 使用当前绝对路径
|
|
Path path = Path.of("src/main/resources", RESOURCE_PATH);
|
|
hikariDataSource.setJdbcUrl("jdbc:sqlite:" + path.toAbsolutePath().toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Bean("sqliteSqlSessionFactory")
|
|
public SqlSessionFactory sqliteSqlSessionFactory(
|
|
@Qualifier("sqliteDataSource") DataSource dataSource) throws Exception {
|
|
|
|
initSQLiteLocation(dataSource);
|
|
|
|
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
|
|
factory.setDataSource(dataSource);
|
|
|
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
|
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.SQLITE));
|
|
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
|
factory.setPlugins(interceptor);
|
|
|
|
return factory.getObject();
|
|
|
|
}
|
|
|
|
@Bean("sqliteSqlSessionTemplate")
|
|
public SqlSessionTemplate sqliteSqlSessionTemplate(@Qualifier("sqliteSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
|
|
return new SqlSessionTemplate(sqlSessionFactory);
|
|
}
|
|
|
|
@Bean(SQLITE_TRANSACTION_MANAGER)
|
|
public DataSourceTransactionManager postgreTransacetionManager(@Qualifier("sqliteDataSource") DataSource dataSource) {
|
|
return new DataSourceTransactionManager(dataSource);
|
|
}
|
|
}
|