MyBatis动态创建SqlSessionFactory

1 篇文章 0 订阅
1 篇文章 0 订阅

一、前言

       云平台上运行了很多项目,根据项目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这个类进行的,这个的创建过程如下:

  1. 定义一个Configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性设置settings
  2. 通过配置对象,则可以创建一个SqlSessionFactoryBuilder对象
  3. 通过 SqlSessionFactoryBuilder 获得SqlSessionFactory 的实例。
  4. 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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值