Spring is a solution to dynamically switch multiple data sources
- 2020-05-30 20:04:53
- OfStack
preface
Spring's dynamic configuration of multiple data sources, i.e. sharding of data in large applications and using multiple database instances for management, can effectively improve the horizontal scalability of the system. Such a scheme will be different from the common single data instance scheme, which requires the program to dynamically decide which database instance to store the data in and which database to extract the data from according to the current request and system state.
Proxy mode is adopted in the later versions of Spring2.x, that is, we implement a virtual data source in the scheme and use it to encapsulate the data source selection logic, so as to effectively separate the data source selection logic from Client. Client provides the context required for selection (because this is known to Client), and the virtual DataSource implements the selection of the data source based on the context provided by Client.
implementation
Specifically, the virtual DataSource only needs to inherit the AbstractRoutingDataSource implementation
determineCurrentLookupKey()
Encapsulates the selection logic for the data source.
1. Dynamically configure multiple data sources
1. Name constant class of data source:
/**
* Configure multiple data sources dynamically
* Name constant class for the data source
* @author LONGHUI_LUO
*
*/
public class DataSourceConst {
public static final String TEST="test";
public static final String USER="User";
}
2. Create a class to obtain and set the context environment, mainly responsible for changing the name of the context data source:
/**
* Gets and sets the context The main responsibility is to change the name of the context data source
*
* @author LONGHUI_LUO
*
*/
public class DataSourceContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal(); // Thread local environment
// Set the data source type
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
// Get data source type
public static String getDataSourceType() {
return (String) contextHolder.get();
}
// Clear data source type
public static void clearDataSourceType() {
contextHolder.remove();
}
}
3. Create the dynamic data source class. Note that this class must inherit AbstractRoutingDataSource and implement the method determineCurrentLookupKey, which returns 1 Object, 1 normally returns a string:
/**
* Setting up a dynamic data source
*
* @author LONGHUI_LUO
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
// In the DAO Before operation, get the type of data source through the context environment variable
return DataSourceContextHolder.getDataSourceType();
}
}
4. Write the configuration file of spring to configure multiple data sources
<!-- The same content for the data source -->
<bean
id="parentDataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property
name="driverClassName"
value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="username" value="sa" />
<property name="password" value="net2com" />
</bean>
<!-- start The features for each data source are configured below -->
<bean parent="parentDataSource" id="testDataSource">
<propertynamepropertyname="url" value="jdbc:sqlserver://localhost:1433;databaseName=test" />
</bean>
<bean parent="parentDataSource" id="UserDataSource">
<property
name="url"
value="jdbc:sqlserver://localhost:1433;databaseName=User" />
</bean>
<!-- end Configure the features of the individual data sources -->
5. Write spring configuration file to configure multi-data source mapping
<bean class="com.xxxx.datasouce.DynamicDataSource" id="dataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="testDataSource" key="test"></entry>
<entry value-ref="UserDataSource" key="User"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="testDataSource" ></property>
</bean>
The first property property in this configuration configures the target data source
,<map key-type="java.lang.String">
The key-type in the static key control class must be of the same type as the value in the static key control class DataSourceConst
;<entry key="User" value-ref="userDataSource"/>
The value of key must be the same as the value in the static key control class, and you can configure multiple values if you have more than one
<
entry
>
The label. The second property property configures the default data source.
Dynamic switching is the data source
DataSourceContextHolder.setDataSourceType(DataSourceConst.TEST);
Advantages of the scheme
First of all, this solution is completely under the framework of spring. The data source is still configured in the configuration file of spring, and sessionFactory is still configured with its dataSource property. It does not even know the change of dataSource. The only difference is that 1 MultiDataSource is added between the true dataSource and sessionFactory.
Second, the implementation is simple and easy to maintain. Although I have said so many things, this scheme is all about analysis. The only code we really need to write is MultiDataSource and SpObserver. The MultiDataSource class really only has to write
getDataSource()
and
getDataSource(sp)
Two methods, and the SpObserver class is simpler. The simpler the implementation, the less likely it is to go wrong and the more maintainable it will be.
Finally, this scheme makes single data sources compatible with multiple data sources. This scheme does not affect the writing of BUS and DAO at all. If our project was developed with a single data source at the beginning and needed to change to multiple data sources as the project progressed, we would only need to modify the spring configuration and slightly modify the MVC layer to write the required data source name in the request and the change would be completed. If our project wants to change the return data source, we only need to modify the configuration file. In this way, more flexibility will be added to our projects.
Disadvantages of the scheme
The failure to solve the problem of sharing the "dataSource" variable when multiple users access the singleton "sessionFactory" leads to a scramble for "dataSource", which is essentially similar to the "producer-consumer" problem in the operating system. Therefore, when multiple users access, multiple data sources may lead to the result of system performance degradation.
conclusion
The above is the whole content of this article, I hope the content of this article to your study or work can bring 1 definite help, if you have questions you can leave a message to communicate.