2015-03-02 16 views
12

Ho bisogno di utilizzare un database per le query (non modificabile) e uno per i comandi (modifica). Sto usando primavera dati APP, quindi ho due classi di configurazione:Spring + JPA + unità di persistenza multiple: Injection 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(); 
    } 

} 

Nel mio archivio ho a volte bisogno di decidere con EntityManager da usare in questo modo:

@Repository 
public class UserReadingRepository { 

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

    // some useful queries here 
} 

Sto usando il nome di unità di persistenza definito nel mio 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> 

primavera getta org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' è definito. Stranamente, sembra che Spring cerchi di istanziare un bean con il nome dell'unità di persistenza? Ho configurato erroneamente qualcosa?

UPDATE: Quando rimuovo unitName = "persistence.reading" da @PersistenceContext annotazione, mi metterò seguente errore invece: 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: Rohit suggerito (nel commento) per cablare EntityManagerFactory invece. Così ho provato a fare quanto segue:

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

ma la primavera riporta solo: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' is defined

FIX FINALE: Grazie alla risposta di Vlad, sono stato in grado di aggiornare il codice per utilizzare il seguente (solo fare assicurarsi di definire il bean dataSource pure):

@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

Perché non si imposta la proprietà 'entityManagerFactory' di' transactionManager'? E dov'è il tuo file 'persistence.xml'? –

+0

'persistence.xml' è su classpath all'interno di' META-INF'. Ho provato a impostare 'entityManagerFactories' sui bean' transactionManager', ma i risultati sono esattamente gli stessi. – Xorty

+0

FYI Sono abbastanza sicuro che 'persistence.xml' è visibile, se torno a utilizzare un solo entityManager, allora Spring assembla con successo tutti i bean. – Xorty

risposta

6

Il EntityManageFactory non è properly configured. Si dovrebbe utilizzare un LocalContainerEntityManagerFactoryBean invece:

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

Anche il JpaTransactionManager è miss-configurato troppo. Dovrebbe essere qualcosa di simile:

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

Hai bisogno di fare la stessa sia per la lettura e la scrittura delle configurazioni EntityManager.

+0

Grazie Vlad, finalmente sono riuscito a farlo funzionare. Si prega di consultare il mio aggiornamento nella domanda originale e di correggere anche la risposta (in modo che compili almeno :)) se anche altre persone riscontrano questo problema. – Xorty

+0

Punto preso. Ho scritto questa risposta da un tablet e stavo giocando il lavoro del compilatore nella mia testa, durante il montaggio. Ho aggiornato la risposta con la correzione finale, per evitare qualsiasi confusione tra domanda e risposta. –

Problemi correlati