Spring Данные JPA: Хранилища для нескольких конфигураций базы данных/Entitymanger

У меня две конфигурации Entitymanager bean. Каждый из них указывает на отдельную базу данных с другой схемой (одна из них - Oracle, другая - в памяти H2)

Что я могу сделать, чтобы решить двусмысленность того, что Entitymanager следует использовать для каждого репозитория? Сейчас я получаю эту ошибку:

 No unique bean of type [javax.persistence.EntityManagerFactory] is defined:
 expected single bean but found 2

Думаю, я мог бы быстро исправить, просто используя что-то вроде

<jpa:repositories base-package="com.foo.repos.ora"
 entity-manager-factory-ref="entityManagerFactoryA">

<jpa:repositories base-package="com.foo.repos.m2"
 entity-manager-factory-ref="entityManagerFactoryB">

Но, надеюсь, есть лучшее решение.

EDIT:

Я даю вам представление о текущем сценарии:

Spring -Config: есть два EM

<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>
<jpa:repositories base-package="com.foo.repos.m2" entity-manager-factory-ref="entityManagerFactory2"/>
<context:component-scan base-package="com.foo" />  ....

Все, что здесь происходит, находится в "пакете com.foo.repos.ora" Следуя шаблону как создать пользовательский репозиторий, я получаю два интерфейса: "ARepository", "ARepositoryCustom" и его реализация "ARepositoryImpl", например,

@Repository
public interface ARepository extends ARepositoryCustom, JpaRepository<myEntity, BigDecimal>, QueryDslPredicateExecutor {

}

public interface ARepositoryCustom {
    FooBar lookupFooBar()
}

public class ARepositoryImpl extends QueryDslRepositorySupport implements ARepositoryCustom {
    ARepositoryImpl(Class<?> domainClass) {
        super(domainClass.class)
    }

    ARepositoryImpl() {
        this(myEntity.class)
    }

    @Override
    FooBar lookupFooBar() {
        JPQLQuery query = ....
        ....
        return found
    }
}

появляется следующее сообщение об ошибке:

Вызвано: org.springframework.beans.factory.BeanCreationException: Ошибка при создании bean с именем " aRepositoryImpl": инъекция ошибки настойчивости не удались; вложенное исключение org.springframework.beans.factory.NoSuchBeanDefinitionException: Нет уникальным bean типа [javax.persistence.EntityManagerFactory] является определенный: ожидаемый сингл bean, но найден 2

Что, конечно, правильно, есть 2 EM beans, но поскольку я ограничил EM # 1 aka 'entityManagerFactory' только для пакета com.foo.repos.ora, я все еще не уверен, как ссылаться точный EM bean.

Ответ 1

Нет волшебства под капотом.

<jpa:repositories base-package="com.foo.repos.ora" entity-manager-factory-ref="entityManagerFactory"/>

не поможет вам с вашими реализациями пользовательского интерфейса. Лучший способ, который я нашел, - рассматривать ваши пользовательские реализации как обычные beans. Поэтому я определил "sharedEntitManager" bean в моей конфигурации spring, например,

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
       ...
</bean>
<bean id="sharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>

После этого я просто ввел EntityManager в мою реализацию beans

<bean id="aRepositoryImpl" class="comm.foo.repos.ora.ARepositoryImpl">
    <property name="entityManager" ref="sharedEntityManager"/>
</bean>

Атрибут 'entity-manager- factory -ref' различает разные фабрики entitymanager, но только для прямых хранилищ данных spring (т.е. только для интерфейсов). Однако он не относится ни к одной из ваших реализаций.

Подводя итог

1), если вы просто полагаетесь на стандартные хранилища данных spring без специальной реализации, используйте атрибут "entity-manager-factory -ref" для различения баз данных.

2a) Кроме того, если вы используете какую-либо пользовательскую реализацию, вставьте соответствующий EntityManager непосредственно в класс реализации. Wirering выполняется под управлением вашей конфигурации spring xml. По какой-то причине я не смог использовать аннотацию @Autowire с @Qualifier для ссылки на правильный EntityManager. EDIT Я только что узнал о @Resource аннотации

@Resource(name =  "sharedEntityManagerA")
EntityManager entityManager


<bean id="sharedEntityManagerA" name="sharedEntityManagerA" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
        <property name = "entityManagerFactory" ref="entityManagerFactory"/>
</bean>

При этом выбор того, что следует использовать EntityMAnger, становится простым. Нет необходимости в сантехнике все, что вам нужно, в вашем контексте xml.

2b). В качестве альтернативы конфигурации spring xml для подключения вашего материала вы также можете пойти с

@PersistenceContext (unitName = "nameOfPersistenceUnit" )

чтобы ввести правильный EntitymanagerFactory

В то время как 'nameOfPersistenceUnit' ссылается на вашу персистенцию, сидящую в стандартном JPA persistence.xml

Однако 2b) не подходит для "QueryDslRepositorySupport", поскольку он ожидает экземпляр EntityManager. Но я обнаружил, что "QueryDslRepositorySupport" не поддерживает много поддержки, поэтому я удалил его.