web-dev-qa-db-ja.com

Springの使用時に複数のJPA EntityManager(持続性ユニット)を挿入する方法

クエリ(非変更)用とコマンド(変更)用に1つのデータベースを使用する必要があります。私はSpring Data JPAを使用しているため、2つの構成クラスがあります。

@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は永続化ユニット名でa 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

PDATE 2:Rohitは(コメントで)代わりにEntityManagerFactoryを配線することを提案しました。だから私は次のことをやろうとしました:

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

ただし、Springは次のレポートのみを報告します:org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'persistence.reading' is defined

最終修正:Vladの回答のおかげで、次のコードを使用するようにコードを更新できました(dataSource Beanも定義していることを確認してください):

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

EntityManageFactory正しく構成された ではありません。代わりに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構成の読み取りと書き込みの両方で同じことを行う必要があります。

8
Vlad Mihalcea