MyBatis动态创建SqlSessionFactory

tech2026-08-05  2

一、前言

       云平台上运行了很多项目,根据项目id动态的切换数据库,mybatis-config.xml启动的时候只会加载一次,很显然无法满足。每次有新项目上线都需要改配置文件然后重启,太low了,所以需要自己根据项目id手动创建SqlSessionFactory进行数据库连接。

       原理:将SqlSessionFactory放入Map集合里,判断对应项目id是否创建SqlSessionFactory,若没创建就创建新的,Map有点话就更加动态切换。

      动态创建SqlSessionFactory有两种方式:

      第一种:是在程序中构建这些对象来创建;

      第二种:是依赖springboot来实现;这种方式打jar提交storm集群的时候始终找不到主类,在spring-boot-maven-plugin和maven-shade-plugin之间痛苦了很久果断放弃了,如果是单纯的java或web项目可以用这样方式,毕竟springboot还是很高效的。接下来说的是第一种。

二、在程序中构建SqlSessionFactory

MyBatis框架主要是围绕着SqlSessionFactory这个类进行的,这个的创建过程如下:

定义一个Configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings通过配置对象,则可以创建一个SqlSessionFactoryBuilder对象通过 SqlSessionFactoryBuilder 获得SqlSessionFactory 的实例。SqlSessionFactory 的实例可以获得操作数据的SqlSession实例,通过这个实例对数据库进行操作

1、重新定义MybatisUtil

package com.siger.storm.utils; import com.siger.storm.mapper.*; import com.siger.storm.model.TableName; import org.apache.ibatis.datasource.pooled.PooledDataSource; import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.transaction.TransactionFactory; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import java.util.concurrent.ConcurrentHashMap; public class MybatisUtil { public static final Logger log = LogManager.getLogger(MybatisUtil.class); public static com.siger.storm.constant.Configuration config = com.siger.storm.constant.Configuration.getInstance(); public static ConcurrentHashMap sessionHashMap = new ConcurrentHashMap(); private static SqlSessionFactory sessionFactory; public static synchronized SqlSession getSqlSession() { SqlSession session = null; try { if (sessionHashMap.get(TableName.getTableName()) != null) { sessionFactory = (SqlSessionFactory) sessionHashMap.get(TableName.getTableName()); if (sessionFactory.openSession() != null) { session = sessionFactory.openSession(); } } else { sessionFactory = CreateSessionFactory(TableName.getTableName()); if (sessionFactory != null) { sessionHashMap.put(TableName.getTableName(), sessionFactory); session = sessionFactory.openSession(); if (sessionFactory.openSession() != null) { session = sessionFactory.openSession(); } } else { log.warn("sessionFactory is null..."); } } } catch (Exception e) { log.error(e.getMessage() + "-->catch Exception"); } return session; } /** * 根据库名动态创建会话 * * @param dbName * @return */ public static synchronized SqlSessionFactory CreateSessionFactory(String dbName) { //创建使用缓存池的数据源 /* * <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> */ // 数据库连接 PooledDataSource dataSource = new PooledDataSource(); dataSource.setDriver(config.getString("cloud.mysql.jdbc.driver", "")); dataSource.setUsername(config.getString("cloud.mysql.user", "")); dataSource.setPassword(config.getString("cloud.mysql.password", "")); dataSource.setUrl(config.getString("cloud.mysql.url", "") + dbName + "?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&autoReconnect=true"); //创建事务 /* * <transactionManager type="JDBC" /> */ // 事务 TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment(dbName, transactionFactory, dataSource); //加入资源 /* * <mapper resource="ssm/BlogMapper.xml"/> */ // 创建configuration信息, 添加映射器 // **Mapper.xml 要放在 **Mapper.class 同一级目录下 Configuration configuration = new Configuration(environment); configuration.addMapper(xxMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); log.info(dbName + " sqlSessionFactory created successfully..."); return sqlSessionFactory; } }

2、新建TableName实体类缓存库名

package com.siger.storm.model; public class TableName { public static ThreadLocal<String>tablename = new ThreadLocal<>(); public static void setTableName(String cid_pid){ tablename.set(cid_pid); } public static String getTableName(){ return tablename.get(); } public static void removeTableName(){ tablename.remove(); } }

3、写个测试类测试一下

至于实体类、xxMapper.class和xMapper.xml生成就不多说了,可以用generator自动生成,log和读取配置文件常量类自定义

package com.siger.storm; import com.siger.storm.dao.impl.ProductionDaoImpl; import com.siger.storm.model.Production; import com.siger.storm.model.TableName; /** * 描述: 测试 * author: weiy * create: 2020-09-04 18:12 */ public class test { public static ProductionDaoImpl pDaoImpl = new ProductionDaoImpl(); public static void main(String[] args) { TableName.setTableName("12_79"); final Production production = new Production(); production.setMachineid(23); production.setStatus(1); pDaoImpl.insert(production); } }

三、注意事项

1、xxMapper.class 和 xxMapper.xml必须在同一级目录下,不然无法识别,底层就是这样定义的,有兴趣朋友可以看下源码。

2、pom.xml需如下配置,不然加载不到src/main/java目录下的xxMapper.xml

最新回复(0)