Đây là những gì tôi đã kết thúc và nó hoạt động khá tốt. Trình quản lý thực thể chỉ có thể có một bean để sử dụng làm nguồn dữ liệu. Vì vậy, những gì tôi phải làm là tạo ra một hạt đậu giữa hai nơi cần thiết. Đó là một trong những ben tôi đã sử dụng cho người quản lý thực thể JPA.
Tôi thiết lập hai nguồn dữ liệu khác nhau trong tomcat. Trong tệp tin server.xml, tôi đã tạo hai tài nguyên (nguồn dữ liệu).
<Resource name="readConnection" auth="Container" type="javax.sql.DataSource"
username="readuser" password="readpass"
url="jdbc:mysql://readipaddress:3306/readdbname"
driverClassName="com.mysql.jdbc.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"
removeAbandoned="true" />
<Resource name="writeConnection" auth="Container" type="javax.sql.DataSource"
username="writeuser" password="writepass"
url="jdbc:mysql://writeipaddress:3306/writedbname"
driverClassName="com.mysql.jdbc.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"
removeAbandoned="true" />
Bạn có thể có các bảng cơ sở dữ liệu trên cùng một máy chủ, trong trường hợp các địa chỉ ip, lĩnh vực sẽ là như nhau, chỉ khác nhau dbs - bạn sẽ có được jist.
Sau đó tôi đã thêm liên kết tài nguyên vào tệp context.xml trong tomcat tham chiếu các tài nguyên này.
<ResourceLink name="readConnection" global="readConnection" type="javax.sql.DataSource"/>
<ResourceLink name="writeConnection" global="writeConnection" type="javax.sql.DataSource"/>
Các liên kết tài nguyên này là những gì mùa xuân đọc trong ngữ cảnh ứng dụng. Trong bối cảnh ứng dụng, tôi đã thêm định nghĩa bean cho mỗi liên kết tài nguyên và thêm một định nghĩa bean bổ sung tham chiếu đến một bean Router Datasource mà tôi đã tạo trong bản đồ (enum) của hai bean đã được tạo trước đó (định nghĩa bean).
<!--
Data sources representing master (write) and slaves (read).
-->
<bean id="readDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="readConnection" />
<property name="resourceRef" value="true" />
<property name="lookupOnStartup" value="true" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<bean id="writeDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="writeConnection" />
<property name="resourceRef" value="true" />
<property name="lookupOnStartup" value="true" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<!--
Provider of available (master and slave) data sources.
-->
<bean id="dataSource" class="com.myapp.dao.DatasourceRouter">
<property name="targetDataSources">
<map key-type="com.myapp.api.util.AvailableDataSources">
<entry key="READ" value-ref="readDataSource"/>
<entry key="WRITE" value-ref="writeDataSource"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="writeDataSource"/>
</bean>
Định nghĩa bean của người quản lý thực thể sau đó tham chiếu bean dataSource.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="${jpa.persistenceUnitName}" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${jpa.dialect}"/>
<property name="showSql" value="${jpa.showSQL}" />
</bean>
</property>
</bean>
Tôi đã xác định một số thuộc tính trong tệp thuộc tính nhưng bạn có thể thay thế giá trị $ {} bằng các giá trị cụ thể của riêng bạn. Vì vậy, bây giờ tôi có một bean sử dụng hai bean khác đại diện cho hai nguồn dữ liệu của tôi. Một trong những đậu là một trong tôi sử dụng cho JPA. Đó là không biết gì về bất kỳ định tuyến xảy ra.
Bây giờ, hạt định tuyến.
public class DatasourceRouter extends AbstractRoutingDataSource{
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException{
// TODO Auto-generated method stub
return null;
}
@Override
protected Object determineCurrentLookupKey(){
return DatasourceProvider.getDatasource();
}
}
Phương thức ghi đè được gọi bởi người quản lý thực thể để xác định nguồn dữ liệu về cơ bản. DatasourceProvider có một thuộc tính cục bộ (thread safe) với phương thức getter và setter cũng như phương thức nguồn dữ liệu rõ ràng để làm sạch.
public class DatasourceProvider{
private static final ThreadLocal<AvailableDataSources> datasourceHolder = new ThreadLocal<AvailableDataSources>();
public static void setDatasource(final AvailableDataSources customerType){
datasourceHolder.set(customerType);
}
public static AvailableDataSources getDatasource(){
return (AvailableDataSources) datasourceHolder.get();
}
public static void clearDatasource(){
datasourceHolder.remove();
}
}
Tôi có một thực hiện DAO chung với các phương pháp tôi sử dụng để xử lý các cuộc gọi JPA thói quen khác nhau (getReference, kiên trì, createNamedQUery & getResultList, vv). Trước khi nó thực hiện cuộc gọi đến thực thểManager để làm bất cứ điều gì nó cần phải làm tôi thiết lập nguồn dữ liệu DatasourceProvider để đọc hoặc ghi. Phương thức này có thể xử lý giá trị đó cũng được truyền vào để làm cho nó trở nên năng động hơn một chút. Đây là một phương pháp ví dụ.
@Override
public List<T> findByNamedQuery(final String queryName, final Map<String, Object> properties, final int... rowStartIdxAndCount)
{
DatasourceProvider.setDatasource(AvailableDataSources.READ);
final TypedQuery<T> query = entityManager.createNamedQuery(queryName, persistentClass);
if (!properties.isEmpty())
{
bindNamedQueryParameters(query, properties);
}
appyRowLimits(query, rowStartIdxAndCount);
return query.getResultList();
}
AvailableDataSources là một enum với READ hoặc WRITE, tham chiếu nguồn dữ liệu thích hợp. Bạn có thể thấy rằng trong bản đồ được định nghĩa trong bean của tôi trên ngữ cảnh ứng dụng.
Ồ, và bạn cần đảm bảo rằng JAR MySQL nằm trong Tomcat, nếu không nguồn dữ liệu (tài nguyên) sẽ không hoạt động. – Elrond
Cảm ơn! Đó là một ý tưởng hay, tôi sẽ có một thử. – Stony
Dưới đây là một số cải tiến của phương pháp này bằng cách sử dụng chú thích tùy chỉnh: http://fedulov.website/2015/10/14/dynamic-datasource-routing-with-spring/ –