2013-02-21 42 views
6

Tôi đã nghiên cứu và tìm thấy một explaination and sample code như thế nào để sử dụng vào mùa xuân JPA dữ liệu với nhiều datasources đó đề cập đến việc cấu hình nhiều JPA: kho trong cấu hình xml như sau:Nhiều jpa: kho lưu trữ trong cấu hình xml, cách cấu hình với @EnableJPARepositories bằng cấu hình Spring java?

<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> 

Làm thế nào bạn sẽ tuyên bố cả hai cấu hình trên: các cấu hình kho lưu trữ sử dụng cấu hình java và chú thích @EnableJpaRepositories?

Chú thích dường như chỉ hỗ trợ một tập hợp thuộc tính (tức là chỉ cho một jpa: chỉ lưu trữ) và không thể khai báo chú thích nhiều lần.

Trả lời

0

Bạn có thể thử đặt nó trên hai lớp @Configuration (một @EnableJpaRepositories trên @Configuration).

17

Tôi đã tạo một dự án nhiều nguồn dữ liệu 'tối thiểu' để giúp tôi tìm hiểu cách thực hiện việc này. Có 7 lớp Java và cấu hình khác trong đó, vì vậy tôi sẽ chỉ đăng các trích xuất chính trong câu trả lời này. Bạn có thể nhận được đầy đủ các dự án từ GitHub: https://github.com/gratiartis/multids-demo

Bản demo thiết lập hai thực thể JPA:

@Entity public class Foo { /* Constructors, fields and accessors/mutators */ } 
@Entity public class Bar { /* Constructors, fields and accessors/mutators */ } 

Associated với những chúng ta sẽ tạo hai kho. Nhờ có sự khiếp sợ của dữ liệu mùa xuân, chúng tôi có thể nhận được bản thân mình một số kho khá đầy đủ tính năng hoàn toàn bằng cách định nghĩa các giao diện mà mở rộng JpaRepository:

public interface FooRepository extends JpaRepository<Foo, Long> {} 
public interface BarRepository extends JpaRepository<Bar, Long> {} 

Bây giờ chúng ta cần phải đảm bảo rằng mỗi người trong các bản đồ này vào một bảng trong cơ sở dữ liệu riêng của mình .

Để đạt được điều này, chúng tôi sẽ cần hai người quản lý thực thể riêng biệt, mỗi người trong số đó có một nguồn dữ liệu khác nhau. Tuy nhiên, trong lớp cấu hình Spring Java @Configuration, chúng tôi chỉ có thể có một chú thích @EnableJpaRepositories và mỗi chú thích như vậy chỉ có thể tham chiếu một EntityManagerFactory. Để đạt được điều này, chúng tôi tạo ra hai lớp riêng biệt @Configuration: FooConfig và BarConfig.

Mỗi lớp @Configuration sẽ xác định một DataSource dựa trên một cơ sở dữ liệu nhúng HSQL:

@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(); 
} 

Mỗi cấu hình cần xác định một EntityManagerFactory, như trên, có sự tham khảo dataSource riêng() phương pháp @Bean của nó. Nó cũng định nghĩa một đường dẫn đến các bean @Entity mà nó quản lý. Bạn cần đảm bảo rằng các hạt @Entity cho các nguồn dữ liệu khác nhau nằm trong các gói khác nhau. Tại thời điểm này, cần lưu ý rằng nếu mỗi cấu hình trong số này sử dụng tên mặc định cho các bean bền vững (tức là entityManagerFactory), thì Spring sẽ thấy rằng có hai bean với giao diện EntityManager, cả hai đều có cùng tên . Vì vậy, người ta sẽ được chọn. Điều này dẫn đến sai sót như:

Not an managed type: class com.sctrcd.multidsdemo.domain.bar.Bar 

Điều này có thể được nhìn thấy trong các chi nhánh của các dự án trình diễn ở đây: https://github.com/gratiartis/multids-demo/tree/1-unnamed-entitymanager-beans

Điều này là do trong ví dụ đó, mùa xuân đã dây lên đậu liên quan đến "foodb "cơ sở dữ liệu và Thanh không phải là một thực thể trong cơ sở dữ liệu đó. Thật không may, BarRepository đã được kết nối với người quản lý thực thể Foo.

Chúng tôi giải quyết vấn đề này bằng cách đặt tên tất cả các hạt của chúng tôi trong mỗi lớp cấu hình. tức là

@Bean(name = "fooDataSource") public DataSource dataSource() { .. } 
@Bean(name = "fooEntityManager") public EntityManager entityManager() { .. } 

Tại thời điểm này nếu bạn đã chạy thử nghiệm trong dự án, bạn có thể thấy cảnh báo như:

No bean named 'entityManagerFactory' is defined. 

này được vì ... Đánh trống ... chúng tôi không có một EntityManagerFactory với tên mặc định là "entityManagerFactory". Chúng ta có một cái gọi là "fooEntityManagerFactory" và một cái gọi là "barEntityManagerFactory". Mùa xuân đang tìm kiếm thứ gì đó có tên mặc định, vì vậy chúng tôi cần hướng dẫn cách kết nối mọi thứ theo cách khác nhau.

Khi nó quay ra, điều này cực kỳ đơn giản để làm. Chúng ta chỉ cần đặt các tham chiếu chính xác trong chú thích @EnableJpaRepositories cho mỗi lớp @Configuration.

@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 { 
    // ... 
} 

Như bạn có thể thấy, mỗi chú thích @EnableJpaRepositories này xác định một tên cụ thể là EntityManagerFactory và PlatformTransactionManager. Họ cũng xác định các kho nên được kết nối với những hạt cà phê đó. Trong ví dụ này, tôi đã đặt các kho lưu trữ trong các gói cơ sở dữ liệu cụ thể. Cũng có thể xác định từng kho lưu trữ riêng lẻ theo tên, bằng cách thêm includeFilters vào chú thích, nhưng bằng cách tách biệt kho lưu trữ theo cơ sở dữ liệu, tôi tin rằng mọi thứ sẽ kết thúc dễ đọc hơn.

Tại thời điểm này, bạn nên có một ứng dụng đang hoạt động bằng cách sử dụng kho dữ liệu Spring để quản lý các thực thể trong hai cơ sở dữ liệu riêng biệt. Cảm thấy tự do để lấy dự án từ liên kết ở trên và chạy các bài kiểm tra để xem điều này xảy ra. Hy vọng rằng câu trả lời này hữu ích cho nhiều người hơn, vì tôi đã dành một khoảng thời gian khá dài để làm điều này một cách rõ ràng nhất có thể với ít mã nhất mà tôi có thể quản lý. Bất kỳ ý tưởng để cải thiện các câu trả lời hoặc dự án demo được chào đón.

Các vấn đề liên quan