2015-03-02 3 views
12

Мне нужно использовать одну базу данных для запросов (немодифицирующих) и одну для команд (модификация). Я использую Spring Data JPA, так что у меня есть два класса конфигурации:Spring + JPA + несколько единиц сохранения: Injecting EntityManager

@Configuration 
@EnableJpaRepositories(value = "com.company.read", 
     entityManagerFactoryRef = "readingEntityManagerFactory", 
     transactionManagerRef = "readingTransactionManager") 
@EnableTransactionManagement 
public class SpringDataJpaReadingConfiguration { 

    @Bean(name = "readingEntityManagerFactory") 
    public EntityManagerFactory readingEntityManagerFactory() { 
     return Persistence.createEntityManagerFactory("persistence.reading"); 
    } 

    @Bean(name = "readingExceptionTranslator") 
    public HibernateExceptionTranslator readingHibernateExceptionTranslator() { 
     return new HibernateExceptionTranslator(); 
    } 

    @Bean(name = "readingTransactionManager") 
    public JpaTransactionManager readingTransactionManager() { 
     return new JpaTransactionManager(); 
    } 

} 

@Configuration 
@EnableJpaRepositories(value = "com.company.write", 
     entityManagerFactoryRef = "writingEntityManagerFactory", 
     transactionManagerRef = "writingTransactionManager") 
@EnableTransactionManagement 
public class SpringDataJpaWritingConfiguration { 

    @Bean(name = "writingEntityManagerFactory") 
    public EntityManagerFactory writingEntityManagerFactory() { 
     return Persistence.createEntityManagerFactory("persistence.writing"); 
    } 

    @Bean(name = "writingExceptionTranslator") 
    public HibernateExceptionTranslator writingHibernateExceptionTranslator() { 
     return new HibernateExceptionTranslator(); 
    } 

    @Bean(name = "writingTransactionManager") 
    public JpaTransactionManager writingTransactionManager() { 
     return new JpaTransactionManager(); 
    } 

} 

В моем хранилище я иногда нужно решить с EntityManager использовать следующим образом:

@Repository 
public class UserReadingRepository { 

    @PersistenceContext(unitName = "persistence.reading") 
    private EntityManager em; 

    // some useful queries here 
} 

Я использую имя единицы сохранения как определены в моем persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
      version="2.0"> 

    <persistence-unit name="persistence.reading" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 
     <non-jta-data-source>ReadingDS</non-jta-data-source> 
     <properties> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> 
      <property name="hibernate.show_sql" value="true" /> 
     </properties> 
    </persistence-unit> 

    <persistence-unit name="persistence.writing" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 
     <non-jta-data-source>WritingDS</non-jta-data-source> 
     <properties> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> 
      <property name="hibernate.show_sql" value="true" /> 
     </properties> 
    </persistence-unit> 

</persistence> 

весна бросает org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' определяется. Как ни странно, похоже, что Spring пытается создать экземпляр bean с сохранением названия единицы? Я что-то неправильно понял?

UPDATE: Когда я удалить unitName = "persistence.reading" из @PersistenceContext аннотацию, я буду получать следующее сообщение об ошибке вместо: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: readingEntityManagerFactory,writingEntityManagerFactory

UPDATE 2: Рохит предложил (в комментарии) телеграфировать EntityManagerFactory вместо. Так что я попытался сделать следующее:

@PersistenceUnit(unitName = "persistence.reading") 
private EntityManagerFactory emf; 

но весна только сообщает: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' is defined

FINAL FIX: Благодаря ответ Влада, я был в состоянии обновить код, чтобы использовать следующее (просто сделать что вы определите dataSource боб, а):

@Bean(name = "readingEntityManagerFactory") 
public EntityManagerFactory readingEntityManagerFactory() { 
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
    em.setPersistenceUnitName("persistence.reading"); 
    em.setDataSource(dataSource()); 
    em.setPackagesToScan("com.company"); 
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
    em.afterPropertiesSet(); 
    return em.getObject(); 
} 
+0

Почему вы не устанавливаете свойство 'entityManagerFactory'' transactionManager'? И где ваш файл 'persistence.xml'? –

+0

'persistence.xml' находится на пути класса внутри' META-INF'. Я попытался установить 'entityManagerFactories' на beansFunctionManager, но результаты будут точно такими же. – Xorty

+0

FYI Я уверен, что 'persistence.xml' видно, если я вернусь к использованию только одного entityManager, то Spring успешно собрал все компоненты. – Xorty

ответ

6

EntityManageFactory не properly configured. Вы должны использовать вместо LocalContainerEntityManagerFactoryBean:

@Bean(name = "readingEntityManagerFactory") 
public EntityManagerFactory readingEntityManagerFactory() { 
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
    em.setPersistenceUnitName("persistence.reading"); 
    em.setDataSource(dataSource()); 
    em.setPackagesToScan("com.company"); 
    em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); 
    em.afterPropertiesSet(); 
    return em.getObject(); 
} 

Также JpaTransactionManager мисс сконфигурированных тоже. Это должно быть что-то вроде:

@Bean(name = "readingTransactionManager") 
public PlatformTransactionManager readingTransactionManager(){ 
    JpaTransactionManager transactionManager = new JpaTransactionManager(); 
    transactionManager.setEntityManagerFactory(readingEntityManagerFactory()); 
    return transactionManager; 
} 

Вы должны сделать то же самое и для чтения и конфигураций письма EntityManager.

+0

Спасибо Владу, я, наконец, смог заставить его работать. Пожалуйста, ознакомьтесь с моим обновлением в исходном вопросе и исправьте свой ответ (чтобы он как минимум компилировался :)), если другие люди тоже столкнутся с этой проблемой. – Xorty

+0

Point принят. Я написал этот ответ с планшета, и во время редактирования я играл в компиляторе. Я обновил ответ с помощью Final Fix, чтобы избежать путаницы в вопросе и ответах. –

Смежные вопросы