Source code: GitHub point here || GitEE point here
1, Relational data source
1. Dynamic data source
The basic functions of dynamic management data source: data source loading, container maintenance, persistent management.
2. Relational database
Different manufacturers of relational databases provide different connection methods, driver packages and driver class names. Java database connection API and JDBC are application program interfaces used in Java language to regulate how client programs access the database. They provide methods such as querying and updating data in the database, and adapt to most relational databases.
3. Adaptive elements
Core elements: driver package, driver class name, URL format, default port.
There are a lot of relational databases, which must be incomplete here. You can improve them by yourself according to your needs.
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 basic API
DriverManager
Basic service API for managing JDBC drivers. Call the method Class.forName to explicitly load the Driver class, which is just suitable for the business scenario of dynamic data source. The data source type is unknown. Once the Driver class is loaded and registered with the DriverManager class, it can be used to establish a connection with the database.
DataSource
The DataSource interface, implemented by the driver supplier, is responsible for establishing the Connection with the database. When accessing the database in the application, it is often used to obtain the Connection object of the operation data.
Connection
The Connection interface represents the Connection with a specific database. To operate on the database data, the first step is to obtain the database Connection. The Connection implementation is like opening a channel between the application and the database. The Connection instance can be obtained through the DriverManager class or DataSource class.
2, Linking and management
Here are the encapsulation ideas of several core classes: modular function, API separately encapsulation. If you need to adapt to handle various data source types, you can abstract them up, customize the adaptation strategy down, and realize the basic awareness under the influence of design mode.
1. Linking tools
Based on DriverManager to manage data source's drive loading, link obtaining, etc.
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 tool class
Provide API configuration to obtain classes, load required data source APIs, close resources and other basic operations.
@Component public class JdbcConfig { /** * Get data source connection */ public Connection getConnection (ConnectionEntity connectionEntity){ String dataTypeName = connectionEntity.getDataTypeName(); String driverClassName = DataSourceType.getDriver(dataTypeName) ; if (driverClassName == null){ throw new RuntimeException("The data source type is not supported") ; } connectionEntity.setDriverClassName(driverClassName); return ConnectionUtil.getConnect(connectionEntity.getDriverClassName(), connectionEntity.getUserName(), connectionEntity.getPassWord(), connectionEntity.getJdbcUrl()) ; } }
3. Data source container
Maintain a Map container, manage the basic requirements of data source addition, deletion, dynamic acquisition, etc.
@Component public class DataSourceFactory { private volatile Map<Integer, DataSource> dataSourceMap = new HashMap<>(); @Resource private JdbcConfig jdbcConfig ; @Resource private ConnectionMapper connectionMapper ; /** * Data source API wrapper */ 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 ; } /** * Get JDBC link */ public JdbcTemplate getById (Integer id){ return new JdbcTemplate(dataSourceMap.get(id)) ; } /** * Remove data source */ public void removeById (Integer id) { dataSourceMap.remove(id) ; } /** * Add data source management * Note the method here, which is called directly after connection verification */ public void addDataSource (ConnectionEntity connectionEntity){ DataSource dataSource = getDataSource(connectionEntity); dataSourceMap.put(connectionEntity.getId(),dataSource) ; } }
4. Process testing
Based on the dynamic data source, query the table data. The operation here represents the known table structure. In fact, the table structure of the dynamic data source needs to obtain the table fields dynamically again to operate. (data dynamic reading and writing in the next section will be explained in detail)
@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 ; } }
3, Batch management
The configuration information of the persistent data source has one more step of configuration information warehousing, and the warehousing information is loaded into the container and acquired dynamically when used.
1. Mapper structure of library table
Table structure to store configuration information, and transform Mapper file.
<mapper namespace="com.dynamic.add.mapper.ConnectionMapper"> <!-- General query mapping results --> <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. Persistent management
Test whether the data source link is successful, the available data source link, and the configuration information are stored in the warehouse.
@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. Dynamic loading
In the container factory class, add an initialization method to load the configuration information of the data source.
@Component public class DataSourceFactory { /** * Initialize JDBC link 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) ; } } } } }
4, Source code address
GitHub·address https://github.com/cicadasmile/data-manage-parent GitEE·address https://gitee.com/cicadasmile/data-manage-parent