Несколько jpa: репозитории в xml config, как настроить с помощью @EnableJPARepositories с помощью Spring java config?

Я исследовал и нашел объяснение и пример кода о том, как использовать весенние данные jpa с несколькими источниками данных, которые относятся к настройке нескольких jpa: репозиториев в xml-конфигурации следующим образом:

      

Как бы вы объявили обе указанные выше конфигурации jpa: репозиториев, используя java-конфигурацию и аннотацию @EnableJpaRepositories?

Кажется, что аннотация поддерживает только один набор атрибутов (т. Е. Только для одного jpa: репозитория), и невозможно объявить аннотацию несколько раз.

Я создал «минимальный» проект с несколькими источниками данных, чтобы помочь мне разобраться, как это сделать. В нем есть 7 classов Java и другая конфигурация, поэтому я буду публиковать только ключевые выдержки в этом ответе. Вы можете получить полный проект от GitHub: https://github.com/gratiartis/multids-demo

Демо создает два объекта JPA:

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

В связи с этим мы создадим два репозитория. Благодаря удивительности Spring Data, мы можем получить некоторые довольно полнофункциональные репозитории, просто определяя интерфейсы, расширяющие JpaRepository:

 public interface FooRepository extends JpaRepository {} public interface BarRepository extends JpaRepository {} 

Теперь нам нужно обеспечить, чтобы каждая из этих карт была в таблице в собственной базе данных.

Для этого нам понадобятся два отдельных менеджера сущностей, каждый из которых имеет другой источник данных. Однако в classе конфигурации Java Spring @Configuration мы можем иметь только одну аннотацию @EnableJpaRepositories и каждая такая аннотация может ссылаться только на один EntityManagerFactory. Для этого мы создаем два отдельных classа @Configuration: FooConfig и BarConfig.

Каждый из этих classов @Configuration будет определять DataSource на основе встроенной базы данных 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(); } 

Каждая конфигурация должна определять EntityManagerFactory, как указано выше, которая ссылается на свой собственный метод dataSource () @Bean. Он также определяет путь к компонентам @Entity, которыми он управляет. Вы должны убедиться, что компоненты @Entity для разных источников данных находятся в разных пакетах.

На этом этапе стоит отметить, что если каждая из этих конфигураций использует по умолчанию названия для ключевых персистентных beans (т.е. entityManagerFactory), то Spring увидит, что есть два компонента с интерфейсом EntityManager, оба из которых имеют одинаковое имя. Таким образом, каждый будет выбран. Это приводит к ошибкам, таким как:

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

Это можно увидеть в разделе демонстрационного проекта здесь: https://github.com/gratiartis/multids-demo/tree/1-unnamed-entitymanager-beans

Это связано с тем, что в этом примере Spring подключила бобы, относящиеся к базе данных «foodb», а Bar не является сущностью в этой базе данных. К сожалению, BarRepository подключен к файловому менеджеру Foo.

Мы разрешаем эту проблему, называя все наши компоненты в каждом из classов конфигурации. т.е.

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

На этом этапе, если вы должны были запустить тесты в проекте, вы можете увидеть предупреждения, такие как:

  No bean named 'entityManagerFactory' is defined. 

Это потому, что … drumroll … у нас нет EntityManagerFactory с именем по умолчанию «entityManagerFactory». У нас есть одно имя «fooEntityManagerFactory», другое – «barEntityManagerFactory». Spring ищет что-то с именем по умолчанию, поэтому нам нужно научить его подключать вещи по-другому.

Как оказалось, это невероятно просто. Нам просто нужно поместить правильные ссылки в аннотацию @EnableJpaRepositories для каждого classа @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 { // ... } 

Как вы можете видеть, каждая из этих аннотаций @EnableJpaRepositories определяет определенный имя EntityManagerFactory и PlatformTransactionManager. Они также указывают, какие репозитории должны быть связаны с этими бобами. В этом примере я разместил репозитории в пакетах, специфичных для базы данных. Также можно определить каждый отдельный repository по имени, добавив includeFilters в аннотацию, но, разделив репозитории по базе данных, я считаю, что все должно стать более читаемым.

На этом этапе у вас должно быть рабочее приложение, использующее хранилища Spring Data для управления объектами в двух отдельных базах данных. Не стесняйтесь захватывать проект из ссылки выше и запускать тесты, чтобы это произошло. Надеюсь, этот ответ полезен для большего количества людей, поскольку я потратил приличное количество времени на то, чтобы сделать это как можно чище, с минимальным кодом, каким я мог бы управлять. Любые идеи для улучшения ответа или демонстрационного проекта приветствуются.

Вы можете попробовать поставить его на два classа @Configuration (один @EnableJpaRepositories за @Configuration ).