自主创建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); } }

图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 }
本地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 }
最后就是准备拿结果了:
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 }
到此,目的达到了。可以通过入参比如数据源ID,可以动态获取某一个数据源的ID下的具体mapper。
由于当时应该是工作的第二年,很多地方写的也不好,我就将关键的地方放上来了。有些描述不对的,请小伙伴指出来。
图1来源:https://blog.csdn.net/u013541707/article/details/113245421
浙公网安备 33010602011771号