博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring-Boot快速集成Sqlite数据库(动态创建,动态切换)
阅读量:3925 次
发布时间:2019-05-23

本文共 9156 字,大约阅读时间需要 30 分钟。

Spring-Boot快速集成Sqlite数据库(动态创建,动态切换)

首先分析集成sqlite,然后需要完成的需求

  1. 动态创建sqlite数据
  2. 动态连接sqlite数据库
  3. 操作sqlite数据库

相比较传统的数据,使用mybaits集成,需要变更是数据库驱动driver,这个需要引入sqlite的依赖

org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.4
org.xerial
sqlite-jdbc
3.27.2.1

配置初始sqlite数据库

# database configurationblog.sqlite.url: jdbc:sqlite:E:/git_space/BlogSqlite/sqlite/pro.db

这里配置的是初始的数据库,文件不用创建,项目启动时会自动创建并初始化数据的表

@MapperScan(basePackages = {
"club.dlblog.sqlite.mapper"}, sqlSessionFactoryRef = "sqlSessionFactory")@Configurationpublic class SqliteConfig {
//数据源url @Value("${blog.sqlite.url}") private String dataSourceUrl; /** * 配置sqlite数据源 * @return */ @Bean(name = "sqliteDataSource") public DataSource sqliteDataSource(){
//尝试创建sqlite文件-不存在时创建 SqliteUtils.initSqliteFile(SqliteUtils.getFilePath(dataSourceUrl)); //创建数据源 DataSource dataSource = SqliteBuilder.create().url(dataSourceUrl).build(); try {
//尝试初始化数据库-表不存在时创建 SqliteUtils.initProDb(dataSource.getConnection()); } catch (SQLException e) {
e.printStackTrace(); } return dataSource; } /** * session工厂 */ @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactory( @Qualifier("dynamicDataSource") DynamicDataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSource); sessionFactoryBean.setMapperLocations( new PathMatchingResourcePatternResolver(). getResources("classpath:mapper/**/*.xml")); return sessionFactoryBean.getObject(); } /** * session模板 * @param sqlSessionFactory * @return */ @Bean(name = "sqlSessionTemplate") public SqlSessionTemplate ComSqlSessionTemplate( @Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory); } /** * 动态数据源 * @param dataSource * @return */ @Bean(name = "dynamicDataSource") public DynamicDataSource dynamicDataSource(@Qualifier("sqliteDataSource") DataSource dataSource){
return new DynamicDataSource(dataSource); }}

在这里需要做两步操作,尝试创建文件,文件不存在时,则去创建文件

//创建sqlite文件    public static void initSqliteFile(String filePath){
File file = new File(filePath); File dir = file.getParentFile(); if(!dir.exists()){
dir.mkdirs(); } if(!file.exists()){
try {
file.createNewFile(); } catch (IOException e) {
e.printStackTrace(); } } }

尝试初始化数据库,当表不存在时初始化数据

/**     * 初始化项目db     * @param connection     */    public static void initProDb(Connection connection){
//判断数据表是否存在 boolean hasPro = false; try {
hasPro = true; //测试数据表是否存在 connection.prepareStatement("select * from pro").execute(); }catch (SQLException e){
//不存在 logger.debug("table pro is not exist"); hasPro = false; } //不存在时创建db if(!hasPro) {
logger.debug(">>>start init pro db"); File file = null; try {
//读取初始化数据sql file = ResourceUtils.getFile("classpath:sql/init.sql"); } catch (FileNotFoundException e) {
e.printStackTrace(); } //获取sql String sql = ""; FileInputStream fis = null; InputStreamReader isr = null; try {
fis = new FileInputStream(file); isr = new InputStreamReader(fis, "UTF-8"); BufferedReader bf = new BufferedReader(isr); String content = ""; StringBuilder sb = new StringBuilder(); while (content != null) {
content = bf.readLine(); if (content == null) {
break; } sb.append(content.trim()); } sql = sb.toString(); } catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace(); } catch (IOException e) {
e.printStackTrace(); } finally {
try {
isr.close(); fis.close(); } catch (IOException e) {
e.printStackTrace(); } } //分割sql String[] sqls = sql.split(";"); try {
for (String str : sqls) {
//开始初始化数据库 connection.setAutoCommit(false); connection.prepareStatement(str).execute(); } //提交sql connection.commit(); } catch (SQLException e) {
e.printStackTrace(); } finally {
try {
connection.close(); } catch (SQLException e) {
e.printStackTrace(); } } logger.debug("finish init pro db>>>"); }else {
logger.debug("pro db is exist"); } }

构建sqlite数据源其实只需要url和驱动类

下面时创建sqlite数据源的方式

public DataSource build(){
//url不为空 if (url!=null&&url!=""){
return DataSourceBuilder.create(). url(url).driverClassName(JDBC.class.getName()).build(); } //文件路径不为空 if(filePath!=null&&filePath!=""){
StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("jdbc:sqlite:").append(filePath); return DataSourceBuilder.create(). url(stringBuilder.toString()).driverClassName(JDBC.class.getName()).build(); } return DataSourceBuilder.create().build(); }

创建动态sqlite数据源

参照我的上一篇的动态数据源的集成方式

/** * 动态数据源配置 * @author machenike */public class DynamicDataSource extends AbstractRoutingDataSource {
private volatile static DynamicDataSource dynamicDataSource; /** * 数据源存储用map */ private final Map
dataSourceMap = new ConcurrentHashMap<>(); /** * 当前线程数据源key */ private final ThreadLocal
contextHolder = new ThreadLocal
(); @Override protected Object determineCurrentLookupKey() {
//弹出当前数据源key return contextHolder.get(); } /** * 动态数据源构造方法 * @param defaultDataSource */ public DynamicDataSource(DataSource defaultDataSource) {
//存入主数据源 dataSourceMap.put("master",defaultDataSource); //设定目标数据源map setTargetDataSources(dataSourceMap); //设定默认数据源 setDefaultTargetDataSource(defaultDataSource); dynamicDataSource = this; } /** * 判断当前数据源是否存在 * * @param dataBaseKey * @return */ public static boolean isExistDataSource(String dataBaseKey) {
if (dynamicDataSource != null) {
return dynamicDataSource.getDataSourceMap().containsKey(dataBaseKey); } else {
return false; } } /** * 切换数据源 * * @param key */ public static void setDataSourceKey(String key) {
if (dynamicDataSource != null) {
dynamicDataSource.getContextHolder().set(key); dynamicDataSource.afterPropertiesSet(); } } /** * 获取当前数据源 * * @return */ public static String getDataSourceKey() {
if (dynamicDataSource != null) {
return dynamicDataSource.getContextHolder().get(); } else {
return null; } } /** * 切换到默认数据源 */ public static void clearDataSourceKey() {
if (dynamicDataSource != null) {
dynamicDataSource.getContextHolder().remove(); } } /** * 根据数据源key设置数据源 * * @param datatBase * @return */ public static void addDataSource(String datatBase, DataSource dataSource) {
if (dynamicDataSource == null) {
return; } // 没有数据源时添加数据源,有数据源直接使用 if (!isExistDataSource(datatBase)) {
// 新增数据源 dynamicDataSource.getDataSourceMap().put(datatBase, dataSource); } // 切换数据源 checkoutDataSource(datatBase); } /** * 切换数据源 * * @param databaseKey */ public static void checkoutDataSource(String databaseKey) {
if (dynamicDataSource != null) {
// 切换数据源 setDataSourceKey(databaseKey); dynamicDataSource.afterPropertiesSet(); } }}

整个流程

  • 项目启动时尝试去链接本地的sqlite数据库
  • 当文件不存在创建文件
  • 当数据表不存在创建表
  • 同时将主数据源放入动态数据源中
  • 启动完主数据库完成链接绑定mapper

后续创建数据源的步骤

  • 创建sqlite文件
  • 初始化数据库
  • 创建新的数据源放入动态数据
  • 通过动态数据源来切换数据库

全部源码的链接

转载地址:http://ahugn.baihongyu.com/

你可能感兴趣的文章
面试官:说说 Springboot 中的 javaConfig(基于Spring5.2)
查看>>
你的钱为什么被转走,这篇文章告诉你答案(CSRF详解)
查看>>
JVM中的一个小知识点:深堆和浅堆的概念
查看>>
HashMap的负载因子初始值为什么是0.75?这篇文章以最通俗的方式告诉你答案
查看>>
详解java中一个面试常问的知识点-阻塞队列
查看>>
除了Thread和Runnable,你还知道第三种创建线程的方式Callable吗
查看>>
java线程面试题集锦(第一版本)
查看>>
记一次java中三元表达式的坑(避免踩坑)
查看>>
面试官:如何实现一个乐观锁(小白都能看得懂的代码)
查看>>
CopyOnWriteArrayList,一个面试中经常问到的冷门容器
查看>>
设计模式之桥接模式
查看>>
设计模式之组合模式
查看>>
java网络编程(1)基础知识点总结
查看>>
java网络编程(2)Socket编程案例(TCP和UDP两种)
查看>>
设计模式之享元模式
查看>>
深入分析java中的多态原理(jvm角度分析)
查看>>
SpringBoot系列(1)基础入门和案例
查看>>
设计模式之命令模式
查看>>
springBoot系列(2)整合MongoDB实现增删改查(完整版)
查看>>
java关键字(6)void
查看>>