Comment s'injecter plusieurs EntityManager (unités de persistance) lors de l'utilisation de Printemps

J'ai besoin d'utiliser une base de données pour les requêtes (sans modification) et un pour les commandes (modifier). Je suis à l'aide de Spring Data JPA, j'ai donc deux classes de configuration:

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

}

Dans mon référentiel j'ai parfois besoin de décider avec l'EntityManager à utiliser comme suit:

@Repository
public class UserReadingRepository {

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

    //some useful queries here
}

Je suis à l'aide de l'unité de persistance du nom tel que défini dans mon 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>

Printemps jette org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' est défini. Bizarrement, on dirait le Printemps essaie d'instancier un haricot avec persistance nom de l'unité? Je n'ai misconfigure quelque chose?

Mise à JOUR: Lorsque je supprime unitName = "persistence.reading" de @PersistenceContext annotation, je vais avoir d'erreur suivant à la place:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: readingEntityManagerFactory,writingEntityManagerFactory

Mise à JOUR 2: Rohit suggéré (dans les commentaires) pour fil EntityManagerFactory à la place. J'ai donc essayé de faire ce qui suit:

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

mais le Printemps seuls les rapports: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' is defined

CORRECTION FINALE:
Merci à Vlad réponse, j'ai été en mesure de mettre à jour le code à utiliser les éléments suivants (assurez-vous de définir votre dataSource bean en tant que bien):

@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();
}
  • Pourquoi n'êtes-vous pas de réglage entityManagerFactory propriété de transactionManager? Et où est votre persistence.xml fichier?
  • persistence.xml est sur le chemin de classe à l'intérieur de META-INF. J'ai tenté de entityManagerFactories sur transactionManager haricots, mais les résultats sont exactement les mêmes.
  • Pour info je suis assez sûr que persistence.xml est visible, si je tombe en arrière à l'aide d'un entityManager puis le Printemps avec succès assemble tous les haricots.
  • Ce qui est étrange. J'ai aussi utilisé plusieurs entityManagers dans ma demande, mais j'ai suivi basé sur Java config approche. Et cela a fonctionné parfaitement, avec différentes unité de persistance des noms. Il devrait y avoir aucune raison pour que cela ne fonctionnerait pas pour les 2, si cela fonctionne pour 1. Ou peut-être, il est très minute chose qui manque quelque part.. j'ai un léger doute avec le nom de PUs.. Cela peut paraître idiot, mais pourriez-vous remplacer . avec -, dans persistence.reading et persistence.writing?
  • heh j'ai déjà pensé à ça et j'ai changé l'unité de persistance des noms, mais malheureusement, pas de chance :-/ j'ai mis à jour la question d'origine avec un autre intéressant d'erreur si
  • Pouvez-vous essayer de câblage EntityManagerFactory plutôt? À l'aide de @PersistenceUnit annotation, en donnant le nom de l'unité. Je soupçonne qu'il a quelque chose à voir avec la transaction-type attribut que vous avez utilisé. Et puis obtenir le entityManager de l'usine.
  • merci d'essayer Rohit, j'ai mis à jour ma question avec la deuxième mise à jour. Toujours bloqué.
  • Étrange.. je suis tombé sur ce post: stackoverflow.com/q/17331024/1679863, donc j'ai pensé que peut être le problème.. Toujours à la recherche de quelque chose de pertinent..
  • Nah je ne prévois pas de durée de mes transactions de plus de 2 bases de données - veux juste dédiée au lit et écrit, donc pas de JTA nécessaire.
  • Vous pourriez probablement obtenir débarrasser de la "Non admissible bean" par exception à l'aide de Qualificatifs. Créer deux annotations (ie.: ReadOnly et ReadWrite). Appliquer le Qualificatif d'annotation sur les deux. Utiliser ces annotations sur le Haricot de méthodes qui retournent des votre les gestionnaires de l'entité. Vous devriez maintenant être en mesure d'injecter les gestionnaires de l'entité en utilisant une combinaison de Autocâblés et l'un de vos nouvelles annotations. Désolé, mais je ne peux pas le tester dès maintenant.
  • c'est la chose étrange. Même si j'utilise Qualifier Printemps ne semble pas le remarquer, il est toujours en train d'injecter de l'EntityManager à l'aide de la même haricot nom est le nom de l'unité de persistance.
  • Je suis aussi en train d'essayer de créer deux entité gestionnaire de l'usine à l'aide approche ci-dessus, mais dans mon cas, la source de données est la même, mais encore obtenir le même problème Pas de qualification bean de type " javax.la persistance.EntityManagerFactory disponibles: unique correspondant bean, mais de 2. Les Pointeurs?

InformationsquelleAutor Xorty | 2015-03-02