數據源管理 | 基於JDBC模式,適配和管理動態數據源
- 2020 年 4 月 7 日
- 筆記
本文源碼: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<>(); @Resource private JdbcConfig jdbcConfig ; @Resource private 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 { @Resource private 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 { @Resource private ConnectionMapper connectionMapper ; @Resource private JdbcConfig jdbcConfig ; @Resource private DataSourceFactory dataSourceFactory ; @Override public boolean testConnection(ConnectionEntity connectionEntity) { return jdbcConfig.getConnection(connectionEntity) !=null ; } @Override public 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 */ @PostConstruct public 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模式讀寫分離 |