数据源管理 | 基于JDBC模式,适配和管理动态数据源
本文源碼:GitHub·點這里 || GitEE·點這里
一、關系型數據源
1、動態數據源
動態管理數據源的基本功能:數據源加載,容器維護,持久化管理。
2、關系型數據庫
不同廠商的關系型數據庫,提供的鏈接方式,驅動包,驅動類名都是不一樣的,Java數據庫連接API,JDBC是Java語言中用來規范客戶端程序如何來訪問數據庫的應用程序接口,提供了諸如查詢和更新數據庫中數據的方法,且適配大部分關系型數據庫。
3、適配要素
核心要素:驅動包、驅動類名、URL格式、默認端口。
關系型數據庫很多,這里一定是不全的,根據需要自行完善即可。
public enum DataSourceType {MySql("MySql", "com.mysql.jdbc.Driver"),Oracle("Oracle", "oracle.jdbc.OracleDriver"),DB2("DB2", "com.ibm.db2.jcc.DB2Driver");private String dataSourceName;private String driverClassName;public static String getDriver (String dataSourceName) {DataSourceType[] types = DataSourceType.values();for (DataSourceType type : types) {if (type.getDataSourceName().equals(dataSourceName)) {return type.getDriverClassName();}}return null;}DataSourceType (String dataSourceName,String driverClassName){this.dataSourceName = dataSourceName ;this.driverClassName = driverClassName ;} }4、JDBC基礎API
DriverManager
管理JDBC驅動程序的基本服務API。調用方法Class.forName,顯式地加載驅動程序類,正好適用于動態數據源的業務場景,數據源類型未知情況。加載Driver類并在DriverManager類注冊后,即可用來與數據庫建立連接。
DataSource
DataSource接口,由驅動程序供應商實現,負責建立與數據庫的連接,當在應用程序中訪問數據庫時,常用于獲取操作數據的Connection對象。
Connection
Connection接口代表與特定的數據庫的連接,要對數據庫數據進行操作,首先要獲取數據庫連接,Connection實現就像在應用程序中與數據庫之間開通了一條通道,通過DriverManager類或DataSource類都可獲取Connection實例。
二、鏈接和管理
這里幾個核心類的封裝思路:模塊化功能,API分開封裝,如果需要適配處理各類數據源類型,則分別可以向上抽象提取,向下自定義適配策略,設計模式影響下的基本意識。
1、鏈接工具
基于DriverManager管理數據源的驅動加載,鏈接獲取等。
public class ConnectionUtil {public static synchronized Connection getConnect(String driverClassName,String userName,String passWord,String jdbcUrl) {Properties prop = new Properties();prop.put("user", userName);prop.put("password", passWord);return connect(driverClassName,prop,jdbcUrl) ;}private static synchronized Connection connect(String driverClassName,Properties prop,String jdbcUrl) {try {Class.forName(driverClassName);DriverManager.setLoginTimeout(JdbcConstant.LOGIN_TIMEOUT);return DriverManager.getConnection(jdbcUrl, prop);} catch (Exception e) {e.printStackTrace();}return null ;}}2、API工具類
提供API配置獲取類,加載需要的數據源API,關閉資源等基本操作。
@Component public class JdbcConfig {/*** 獲取數據源連接*/public Connection getConnection (ConnectionEntity connectionEntity){String dataTypeName = connectionEntity.getDataTypeName();String driverClassName = DataSourceType.getDriver(dataTypeName) ;if (driverClassName == null){throw new RuntimeException("不支持該數據源類型") ;}connectionEntity.setDriverClassName(driverClassName);return ConnectionUtil.getConnect(connectionEntity.getDriverClassName(),connectionEntity.getUserName(),connectionEntity.getPassWord(),connectionEntity.getJdbcUrl()) ;}}3、數據源容器
維護一個Map容器,管理數據源的添加,刪除,動態獲取等基本需求。
@Component public class DataSourceFactory {private volatile Map<Integer, DataSource> dataSourceMap = new HashMap<>();@Resourceprivate JdbcConfig jdbcConfig ;@Resourceprivate ConnectionMapper connectionMapper ;/*** 數據源API包裝*/private static DataSource getDataSource (ConnectionEntity connectionEntity){DruidDataSource datasource = new DruidDataSource();datasource.setUrl(connectionEntity.getJdbcUrl());datasource.setUsername(connectionEntity.getUserName());datasource.setPassword(connectionEntity.getPassWord());datasource.setDriverClassName(connectionEntity.getDriverClassName());return datasource ;}/*** 獲取 JDBC 鏈接*/public JdbcTemplate getById (Integer id){return new JdbcTemplate(dataSourceMap.get(id)) ;}/*** 移除 數據源*/public void removeById (Integer id) {dataSourceMap.remove(id) ;}/*** 添加數據源管理* 注意這里的方法,連接驗證之后直接調用*/public void addDataSource (ConnectionEntity connectionEntity){DataSource dataSource = getDataSource(connectionEntity);dataSourceMap.put(connectionEntity.getId(),dataSource) ;} }4、流程測試
基于動態的數據源,查詢表數據,這里操作的表示已知的表結構,實際上動態數據源的表結構都是需要再次動態獲取表字段,才能操作。(下節數據動態讀取和寫入會詳說)
@Api(value = "JdbcQueryController") @RestController public class JdbcQueryController {@Resourceprivate DataSourceFactory dataSourceFactory ;@GetMapping("getList")public List<ConnectionEntity> getList (@RequestParam("id") Integer id){String sql = "SELECT * FROM jm_connection WHERE state='1'" ;JdbcTemplate jdbcTemplate = dataSourceFactory.getById(id);List<ConnectionEntity> connectionEntities = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(ConnectionEntity.class));return connectionEntities ;} }三、批量管理
持久化數據源的配置信息,多了一步配置信息入庫,和入庫信息加載到容器,使用時動態獲取。
1、庫表Mapper結構
存儲配置信息的表結構,轉換Mapper文件。
<mapper namespace="com.dynamic.add.mapper.ConnectionMapper"><!-- 通用查詢映射結果 --><resultMap id="BaseResultMap" type="com.dynamic.add.entity.ConnectionEntity"><id column="id" property="id" /><result column="data_type_name" property="dataTypeName" /><result column="driver_class_name" property="driverClassName" /><result column="jdbc_url" property="jdbcUrl" /><result column="user_name" property="userName" /><result column="pass_word" property="passWord" /><result column="create_time" property="createTime" /><result column="update_time" property="updateTime" /><result column="state" property="state" /></resultMap><select id="getAllList" resultMap="BaseResultMap" >SELECT * FROM jm_connection WHERE state='1'</select> </mapper>2、持久化管理
測試數據源鏈接是否成功,可用的數據源鏈接,配置信息入庫保存。
@Service public class ConnectionServiceImpl implements ConnectionService {@Resourceprivate ConnectionMapper connectionMapper ;@Resourceprivate JdbcConfig jdbcConfig ;@Resourceprivate DataSourceFactory dataSourceFactory ;@Overridepublic boolean testConnection(ConnectionEntity connectionEntity) {return jdbcConfig.getConnection(connectionEntity) !=null ;}@Overridepublic boolean addConnection(ConnectionEntity connectionEntity) {Connection connection = jdbcConfig.getConnection(connectionEntity) ;if (connection !=null){int addFlag = connectionMapper.insert(connectionEntity);if (addFlag > 0){dataSourceFactory.addDataSource(connectionEntity) ;return true ;}}return false ;} }3、動態加載
容器工廠類中,添加一個初始化的方法,加載入庫的數據源配置信息。
@Component public class DataSourceFactory {/*** 初始化 JDBC 鏈接API*/@PostConstructpublic void init (){List<ConnectionEntity> connectionList = connectionMapper.getAllList();if (connectionList != null && connectionList.size()>0){for (ConnectionEntity connectionEntity:connectionList) {Connection connection = jdbcConfig.getConnection(connectionEntity) ;if (connection != null){DataSource dataSource = getDataSource(connectionEntity);dataSourceMap.put(connectionEntity.getId(),dataSource) ;}}}} }四、源代碼地址
GitHub·地址 https://github.com/cicadasmile/data-manage-parent GitEE·地址 https://gitee.com/cicadasmile/data-manage-parent推薦閱讀:數據管理
| 01 | 數據源管理:主從庫動態路由,AOP模式讀寫分離 |
總結
以上是生活随笔為你收集整理的数据源管理 | 基于JDBC模式,适配和管理动态数据源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle DB死锁
- 下一篇: 数据仓库组件:HBase集群环境搭建和应