2013-02-21 2 views
6

나는 연구와 여러 여러 JPA를 구성을 참조 데이터 소스와 스프링 데이터 JPA 사용하는 방법과 같은 explaination and sample code 발견 : 다음과 같이 XML 구성 저장소 :여러 jpa : xml config의 저장소, @EnableJPARepositories를 사용하여 Spring java config를 사용하여 구성하는 방법은 무엇입니까?

<jpa:repositories base-package="org.springframework.data.jpa.repository.sample" 
    entity-manager-factory-ref="entityManagerFactory"> 
    <repository:exclude-filter type="assignable" expression="org.springframework.data.jpa.repository.sample.AuditableUserRepository" /> 
</jpa:repositories> 
<jpa:repositories base-package="org.springframework.data.jpa.repository.sample" 
    entity-manager-factory-ref="entityManagerFactory-2" 
    transaction-manager-ref="transactionManager-2"> 
    <repository:include-filter type="assignable" expression="org.springframework.data.jpa.repository.sample.AuditableUserRepository" /> 
</jpa:repositories> 

을 당신이 선언 할 방법을 위의 jpa : 저장소 구성에서 Java 구성과 @EnableJpaRepositories 주석을 사용하고 있습니까?

주석은 하나의 속성 세트 (즉, 하나의 jpa : 저장소에만 해당)를 지원하는 것으로 보이며 주석을 여러 번 선언 할 수 없습니다.

답변

0

두 개의 @Configuration 클래스 (@EnableJpaRepositories/@Configuration)에 넣으십시오.

17

필자는이를 수행하는 방법을 이해할 수 있도록 '최소의'다중 데이터 소스 프로젝트를 만들었습니다. 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를 추가하여 각 저장소를 이름으로 정의 할 수도 있지만 데이터베이스별로 저장소를 분리하면 더 쉽게 읽을 수있게됩니다.

이 시점에서 스프링 데이터 저장소를 사용하여 두 개의 개별 데이터베이스에있는 엔티티를 관리하는 작업 응용 프로그램이 있어야합니다. 위의 링크에서 프로젝트를 가져 와서이 문제를 확인하기 위해 테스트를 실행하십시오. 다행히도이 답변은 더 많은 사람들에게 유용합니다. 관리 할 수있는 코드를 가능한 한 깔끔하게 정리하는 데 상당한 시간을 할애했습니다. 답변이나 데모 프로젝트의 개선을위한 아이디어는 언제나 환영합니다.

관련 문제