내가 끝내었던 것은 이것이다. 그리고 그것은 아주 잘 돌아갔다. 엔티티 관리자는 데이터 소스로 사용할 빈 하나만 가질 수 있습니다. 그래서 내가해야만하는 것은 두 곳 사이에서 필요할 때마다 라우팅되는 bean을 만드는 것입니다. JPA 엔티티 관리자에 사용했던 벤 한 개입니다.
나는 tomcat에서 두 가지 다른 데이터 소스를 설정했다. server.xml에서는 두 가지 리소스 (데이터 소스)를 만들었습니다.
<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" />
당신은 IP 주소 나 도메인이 같은 단지 다른 DBS 될 경우에 동일한 서버에 데이터베이스 테이블을 가질 수있다 - 당신이 JIST를 얻을.
다음 리소스를 참조하는 tomcat의 context.xml 파일에 리소스 링크를 추가했습니다.
<ResourceLink name="readConnection" global="readConnection" type="javax.sql.DataSource"/>
<ResourceLink name="writeConnection" global="writeConnection" type="javax.sql.DataSource"/>
이러한 리소스 링크는 응용 프로그램 컨텍스트에서 스프링을 읽는 것과 같습니다.
응용 프로그램 컨텍스트에서 각 자원 링크에 대한 bean 정의를 추가하고 이전에 작성된 두 bean (bean 정의)의 맵 (enum)을 취하는 데이터 소스 라우터 bean을 참조하는 추가 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>
그러면 엔티티 관리자 bean 정의가 dataSource bean을 참조합니다.
<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>
속성 파일에서 일부 속성을 정의했지만 $ {} 값을 사용자 고유의 특정 값으로 바꿀 수 있습니다. 이제 두 개의 다른 데이터 소스를 나타내는 다른 두 개의 빈을 사용하는 한 개의 빈을 갖게되었습니다. 하나의 bean은 JPA에서 사용하는 bean입니다. 라우팅 문제가 발생하지 않습니다.
이제 라우팅 빈.
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();
}
}
재정의 된 메소드는 기본적으로 데이터 소스를 결정하기 위해 엔티티 관리자에 의해 호출됩니다. DatasourceProvider에는 getter 및 setter 메서드가있는 스레드 로컬 (스레드 안전) 속성과 정리를위한 데이터 소스 메서드가 있습니다.
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();
}
}
은 내가 (의 getReference이 지속, createNamedQUery & getResultList 등) 다양한 일상 JPA의 통화를 처리하는 데 사용하는 방법과 일반적인 DAO 구현을 가지고있다. entityManager에 대한 호출을하기 전에 필요한 모든 작업을 수행하기 위해 DatasourceProvider의 데이터 소스를 읽기 또는 쓰기로 설정합니다. 이 메소드는 전달되는 값을 처리하여 좀 더 동적으로 처리 할 수 있습니다. 다음은 예제 메서드입니다.
AvailableDataSources는 적절한 데이터 소스를 참조하는 READ 또는 WRITE가있는 열거 형입니다. 애플리케이션 컨텍스트에서 내 bean에 정의 된 맵에서이를 볼 수있다.
아, MySQL JAR이 Tomcat에 있는지 확인해야합니다. 그렇지 않으면 데이터 소스 (자원)가 작동하지 않습니다. – Elrond
감사! 좋은 생각인데 시험해 볼게. – Stony
다음은 맞춤 주석을 사용하여이 메소드의 일부 향상된 기능입니다. http://fedulov.website/2015/10/14/dynamic-datasource-routing-with-spring/ –