필자는이를 수행하는 방법을 이해할 수 있도록 '최소의'다중 데이터 소스 프로젝트를 만들었습니다. Java 클래스 7 개와 다른 설정이 있으므로이 답변에 키 추출 만 게시 할 것입니다. 당신은 GitHub의에서 전체 프로젝트를 얻을 수 있습니다 : 우리는 두 개의 저장소를 생성합니다 다음과
@Entity public class Foo { /* Constructors, fields and accessors/mutators */ }
@Entity public class Bar { /* Constructors, fields and accessors/mutators */ }
관련 : https://github.com/gratiartis/multids-demo는
데모는 두 JPA 엔티티를 설정합니다.
public interface FooRepository extends JpaRepository<Foo, Long> {}
public interface BarRepository extends JpaRepository<Bar, Long> {}
이제 우리는 자체 데이터베이스의 테이블에이지도의 각을 확인해야합니다 : 봄 데이터의 awesomeness에 덕분에, 우리는 JpaRepository를 확장 인터페이스를 정의하여 자신에게 꽤 완전한 기능을 갖춘 저장소를 순수하게 얻을 수 있습니다 .
이 작업을 수행하려면 두 개의 별도 엔티티 관리자가 필요하며 각 엔티티 관리자마다 서로 다른 데이터 소스가 필요합니다. 그러나 Spring Java 구성 @Configuration
클래스에서는 @EnableJpaRepositories
주석을 하나만 가질 수 있으며 이러한 각 주석은 하나의 EntityManagerFactory 만 참조 할 수 있습니다. 이를 위해 두 개의 별도 @Configuration
클래스 인 FooConfig와 BarConfig를 만듭니다. 각각의 구성은 상기와 같이, EntityManagerFactory를 정의한다
@Bean(name = "fooDataSource")
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setName("foodb").setType(EmbeddedDatabaseType.HSQL).build();
}
@Bean(name = "barDataSource")
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setName("bardb").setType(EmbeddedDatabaseType.HSQL).build();
}
@Bean(name = "barEntityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef =
new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.sctrcd.multidsdemo.domain.bar");
lef.setPersistenceUnitName("barPersistenceUnit");
lef.afterPropertiesSet();
return lef.getObject();
}
@Bean(name = "fooEntityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef =
new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.sctrcd.multidsdemo.domain.foo");
lef.setPersistenceUnitName("fooPersistenceUnit");
lef.afterPropertiesSet();
return lef.getObject();
}
자체는 dataSource() @Bean 방법 참조 :
이러한 @Configuration 클래스 각각
는 내장 HSQL 데이터베이스를 기반으로 데이터 소스를 정의한다. 또한 관리하는 @Entity bean에 대한 경로도 정의합니다. 다른 데이터 소스의 @Entity bean이 다른 패키지에 있는지 확인해야합니다.
이 시점에서 각각의 구성에서 키 지속성 bean (즉, entityManagerFactory)에 대한 기본 이름을 사용하면 Spring은 EntityManager 인터페이스와 함께 두 개의 Bean이 동일한 이름을 가짐을 볼 수 있습니다 . 그래서 하나가 선택 될 것입니다. 이 예에서, 봄은 "foodb에 관한 콩을 유선 때문에 https://github.com/gratiartis/multids-demo/tree/1-unnamed-entitymanager-beans
이것은 :
Not an managed type: class com.sctrcd.multidsdemo.domain.bar.Bar
이
여기 데모 프로젝트의 지점에서 볼 수있다 :이 같은 오류로 연결 "데이터베이스이고 Bar는 해당 데이터베이스의 엔티티가 아닙니다. 불행히도 BarRepository는 Foo 엔티티 관리자와 연결되었습니다.
우리는 각 config 클래스에있는 모든 bean의 이름을 지정하여이 문제를 해결합니다. 즉
프로젝트에서 테스트를 실행한다면이 시점에서
@Bean(name = "fooDataSource") public DataSource dataSource() { .. }
@Bean(name = "fooEntityManager") public EntityManager entityManager() { .. }
, 당신은 다음과 같은 경고가 표시 될 수 있습니다
No bean named 'entityManagerFactory' is defined.
이 드럼 롤 ... 우리가하지 않아도됩니다 ... 때문에를 디폴트의 이름 「entityManagerFactory」를 가지는 EntityManagerFactory 하나는 "fooEntityManagerFactory"이고 다른 하나는 "barEntityManagerFactory"입니다. Spring은 기본 이름을 가진 무언가를 찾으므로, 상황을 다르게 연결하도록 지시해야합니다.
사실, 이것은 매우 간단합니다. 각 @Configuration 클래스에 대해 @EnableJpaRepositories 주석에 올바른 참조를 넣기 만하면됩니다.
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "fooEntityManagerFactory",
transactionManagerRef = "fooTransactionManager",
basePackages = {"com.sctrcd.multidsdemo.integration.repositories.foo"})
public class FooConfig {
// ...
}
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "barEntityManagerFactory",
transactionManagerRef = "barTransactionManager",
basePackages = { "com.sctrcd.multidsdemo.integration.repositories.bar" })
public class BarConfig {
// ...
}
당신이 볼 수 있듯이
이 @EnableJpaRepositories 주석의 각각의 EntityManagerFactory와 PlatformTransactionManager를라는 이름의 특정을 정의합니다. 그들은 또한 어떤 저장소가 그 빈들과 연결되어야 하는지를 지정합니다. 이 예제에서는 저장소를 데이터베이스 별 패키지에 넣었습니다. 어노테이션에 includeFilters를 추가하여 각 저장소를 이름으로 정의 할 수도 있지만 데이터베이스별로 저장소를 분리하면 더 쉽게 읽을 수있게됩니다.
이 시점에서 스프링 데이터 저장소를 사용하여 두 개의 개별 데이터베이스에있는 엔티티를 관리하는 작업 응용 프로그램이 있어야합니다. 위의 링크에서 프로젝트를 가져 와서이 문제를 확인하기 위해 테스트를 실행하십시오. 다행히도이 답변은 더 많은 사람들에게 유용합니다. 관리 할 수있는 코드를 가능한 한 깔끔하게 정리하는 데 상당한 시간을 할애했습니다. 답변이나 데모 프로젝트의 개선을위한 아이디어는 언제나 환영합니다.