自主创建mybtis管理应用,用以横向管理数据源

这个是我写的第一个随手小记,一晃眼做后端开发也有7年多了,现在也准备将一些杂七杂八的资料整理下。也算是回顾这7年中做的比较有意思的东西了。

这个需求是我17年做的,当时的应用场景是仓储库比较多,随时会动态的开启和关闭。好在数据库的表结构是一致的。需要针对不同的库将商品进行有效的管理起来。考虑到数据源是动态变化的,那么使用spring架构下的多数据源配置是行不通。因为表名一致,而且数据源是动态变化的,最少也有90多家的数据,手工配置会死人的。那换成java的jdbc管理呢,最基本的那个,考虑到现在都到mybatis进行数据库管理了。往回退也不好。那么就花了几天出了这个方案。废话不说了,开工...... 第一次写博客还是有点小激动啊。

首先需要手动获取spring的application,从而手动进行资源的注入。将代码的独立性做起来。

/**
 * Created by Dean on 2017/10/19.
 * 获取SpringApplicationContext信息获取 该方法可以不用通过注入形式获取相关数据
 */
@Component
public class SpringApplictionAuto implements ApplicationContextAware {
    // Spring应用上下文环境
    private static ApplicationContext applicationContext;
    /**
     * 实现ApplicationContextAware接口的回调方法,设置上下文环境
     *
     * @param applicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringApplictionAuto.applicationContext = applicationContext;
    }
    /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
    /**
     * 获取对象
     *
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
}
View Code

 

图1: Mybatis的大致结构

 

1 public SqlSessionTemplate getLocalMybatislSession() {
2         ApplicationContext applicationContext = SpringApplictionAuto.getApplicationContext();
3         SqlSessionFactory defaultSqlSessionFactory = (SqlSessionFactory) applicationContext.getBean("sqlSessionFactory");
4         SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(defaultSqlSessionFactory);
5         return sqlSessionTemplate;
6     }
获取本地SqlSessionTemplate

本地SqlSession获取好后那么后面就是重头戏了。

我们首先需要获取的有以下几点:

  • 数据库连接说明
  • 数据库账号信息(没有相关信息也连不上数据库,当然数据库密码小伙伴们打算用密文还是明文,都是随意的。密文的话需要双向加密方式,明文吗,倒是随时可以查其他系统数据库了)
  • 数据库mapper组信息
  • 数据库mapper具体地址
  • 数据库mapper组和mapper的具体关联
  • 数据库配置参数表,其中还有类型处理器

后面就是依次创建SqlSessionFactoryBean,SqlSessionFactory,DruidDataSource,Configuration,TypeHandler[]

 1 /**
 2      * 通过数据库相关信息与mybatis相对应的信息创建 SqlSessionFactory
 3      *
 4      * @param hospitalDbInfoEntity          数据库相关信息
 5      * @param hospitalMapperEntityArrayList 该数据源下存在相应的mapper信息
 6      * @return 返回SqlSessionFactory
 7      * @throws Exception 创建失败时会返回异常
 8      */
 9     public SqlSessionFactory buildSqlSessionFactory(SqlSessionFactoryBean factoryBean, HospitalDbInfoEntity hospitalDbInfoEntity, ArrayList<HosMapper> hospitalMapperEntityArrayList) throws Exception {
10         DruidDataSource dataSource  =new DruidDataSource();
11         dataSource.setDefaultAutoCommit(true);
12         dataSource.setUrl(hospitalDbInfoEntity.getUrl());
13         dataSource.setPassword(hospitalDbInfoEntity.getPassword());
14         dataSource.setUsername(hospitalDbInfoEntity.getUser());
15         dataSource.setDriverClassName(hospitalDbInfoEntity.getDriver_name());
16         
17         dataSource.setInitialSize(50);
18         dataSource.setMaxActive(100);
19         dataSource.setMaxIdle(50);
20         dataSource.setMinIdle(30);
21         dataSource.setRemoveAbandoned(true);
22         dataSource.setRemoveAbandonedTimeout(180);
23         dataSource.setFilters("stdout");
24         dataSource.setResetStatEnable(false);
25         dataSource.setMaxWait(600000);
26         dataSource.setTimeBetweenEvictionRunsMillis(300000);
27         dataSource.setMinEvictableIdleTimeMillis(600000);
28         dataSource.setValidationQuery("SELECT 1 from dual");
29         dataSource.setTestOnBorrow(true);
30         dataSource.setTestOnReturn(false);
31         dataSource.setTestWhileIdle(true);
32         factoryBean.setDataSource(dataSource);
33         String paths = "";
34         factoryBean.setMapperLocations(getMapperResource(hospitalMapperEntityArrayList));
35         Configuration configuration = buildConfiguration();
36         factoryBean.setConfiguration(configuration);
37         factoryBean.setTypeHandlers(buildTypeHandlers(configuration));
38         SqlSessionFactory sqlSessionFactory = factoryBean.getObject();
39         return sqlSessionFactory;
40     }
部分创建代码

上面这块设置好后就是后面拿结果了,结果还是封装到了SqlSessionTemplate中。

 1 /**
 2      * 创建SqlSession信息通过医院Id值
 3      *
 4      * @param hospitalId 数据库中对应的唯一键值
 5      * @return 返回创建好的数据库连接信息
 6      */
 7     public SqlSessionTemplate buildSqlSession(Integer hospitalId) {
 8         SqlSession localSession = getLocalSession();
 9         HosConnIdMapper hosConnIdMapper = localSession.getMapper(HosConnIdMapper.class);
10         HosMapperMapper hosMapperMapper =  localSession.getMapper(HosMapperMapper.class);
11         HospitalDbInfoEntity hospitalDbInfoEntity = hosConnIdMapper.findHospitalEntity(hospitalId);
12 
13         if (hospitalDbInfoEntity == null) {
14             return null;
15         }
16         ArrayList<HosMapper> hospitalMapperEntityArrayList = (ArrayList<HosMapper>) hosMapperMapper.findByHospitalId(hospitalId);
17         if (hospitalMapperEntityArrayList.size() == 0) {
18             return null;
19         }
20         SqlSessionFactory sqlSessionFactory;
21         try {
22             sqlSessionFactory = buildSqlSessionFactory(hospitalId.toString(), hospitalDbInfoEntity, hospitalMapperEntityArrayList);
23         } catch (Exception e) {
24             e.printStackTrace();
25             return null;
26         }
27         sqlSessionFactoryHashMap.put(hospitalId.toString(), sqlSessionFactory);
28         SqlSessionTemplate sqlSession = new SqlSessionTemplate(sqlSessionFactory);
29         dataPools.put(hospitalId.toString(), sqlSession);
30         return sqlSession;
31     }
创建SqlSessionTemplate

最后就是准备拿结果了:

 1 /**
 2      * 获取mybatis中Mapper信息
 3      *
 4      * @param mapper     mybatis 相关dao层类名
 5      * @param hospitalId mybatis连接的
 6      * @param <T>        自定义类型可供不同的mapper进行使用
 7      * @return 返回Mapper信息
 8      */
 9     public <T> T getMapperInstance(Class<T> mapper, Integer hospitalId) {
10         SqlSessionTemplate sqlSession;
11 
12         if (hospitalId == 0) {
13             sqlSession = dataPools.get("localSession");//本地连接
14         } else {
15             sqlSession = dataPools.get(hospitalId.toString());
16         }
17         if (sqlSession == null) {
18             sqlSession = buildSqlSession(hospitalId);
19         }
20         return SqlSessionUtils.getSqlSession(sqlSession.getSqlSessionFactory(),sqlSession.getExecutorType(),sqlSession.getPersistenceExceptionTranslator()).getMapper(mapper);
21     }
获取具体的mapper

到此,目的达到了。可以通过入参比如数据源ID,可以动态获取某一个数据源的ID下的具体mapper。

由于当时应该是工作的第二年,很多地方写的也不好,我就将关键的地方放上来了。有些描述不对的,请小伙伴指出来。

 

 图1来源:https://blog.csdn.net/u013541707/article/details/113245421

posted @ 2022-09-06 10:19  DeanXue  阅读(38)  评论(0)    收藏  举报