0

spring 3.2.3 と JPA 2.0 を使用しています。列挙型に基づいてデータベースを動的に接続したい。私はこのような構成を持っています

<bean id="legacyDataSource" name="myLegacyDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
    <property name="driverClassName" value="${jdbc.legacy.driverClassName}" />
    <property name="url" value="${jdbc.legacy.url}" />  
    <property name="username" value="${jdbc.legacy.username}" />
    <property name="password" value="${jdbc.legacy.password}" />
</bean>

 <bean id="modernDataSource" name="myModernDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
    <property name="driverClassName" value="${jdbc.modern.driverClassName}" />
    <property name="url" value="${jdbc.modern.url}" />  
    <property name="username" value="${jdbc.modern.username}" />
    <property name="password" value="${jdbc.modern.password}" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf"/>
</bean>

<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:database/jdbc.properties" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="order" value="1" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="emf" name="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" ref="vendorAdaptor" />         
    <property name="packagesToScan" value="com.softech.ls360.integration.regulators.plcb.domain"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">10</prop>
            <prop key="hibernate.show_sql">true</prop>              
        </props>        
    </property>
</bean>   

私は列挙型を次のように宣言しました

public enum DatabaseType {

    LEGACY,
    MODERN

} //end of enum DatabaseType

今、データベーススイッチの列挙に基づいてメインクラスが必要です。このために、私は変更する必要があると思います

<property name="dataSource" ref="dataSource" />

実行時に<bean id="emf" name="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true">。私は正しいですか?

それを行う方法はありますか、または春は実行時にデータベースを切り替える他の方法を提供していますか?

この記事Dynamic DataSource Routingを見つけましたが、これは非常に古い投稿であり、この投稿でも JPA は使用されていません。親切に助けて

ありがとう。

編集 - - - - - - - - - - - - - - - -

@Lazy
@Service("dbManager") 
@Repository
@Transactional
public class DatabaseManager {

    public enum EnumLmsPlateform {      
        MODERN,
        LEGACY;
    }

    private EnumLmsPlateform lmsPlatform;

    public EnumLmsPlateform getLmsPlatform() {
        return lmsPlatform;
    }

    public void setLmsPlatform(EnumLmsPlateform lmsPlatform) {
        this.lmsPlatform = lmsPlatform;
    }

    @PostConstruct
    public void init() {    
        setLmsPlatform(EnumLmsPlateform.MODERN);    
    }

    @PersistenceContext(unitName="legacy_emf")
    private EntityManager legacyEm;

    @PersistenceContext(unitName="modern_emf")
    private EntityManager ls360Em;

    @SuppressWarnings("unchecked")
    @Transactional(readOnly=true)
    public List<Object> getResultList(String query, Class<?> mappingClass) throws Exception {

        EntityManager em = null;

        if (lmsPlatform == EnumLmsPlateform.LEGACY) {
            em = legacyEm;  
        } else if (lmsPlatform == EnumLmsPlateform.MODERN){ 
            em = ls360Em;   
        }
        Query emQuery = em.createNativeQuery(query, mappingClass);  
        return  emQuery.getResultList();

    } //end of findTraineeFromLegacy()
} //end of class

ここに私の春のファイルがあります

レガシー-spring.xml

<bean id="legacyDataSource" name="legacy_DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" lazy-init="true">
    <property name="driverClassName" value="${jdbc.legacy.driverClassName}" />
    <property name="url" value="${jdbc.legacy.url}" />  
    <property name="username" value="${jdbc.legacy.username}" />
    <property name="password" value="${jdbc.legacy.password}" />
</bean>

<bean id="legacyTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" lazy-init="true">
    <property name="entityManagerFactory" ref="legacyEmf"/>
</bean>

<tx:annotation-driven transaction-manager="legacyTransactionManager"  />

<bean id="legacyEmf" name="legacy_emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true" >
    <property name="dataSource" ref="legacyDataSource" />
    <property name="jpaVendorAdapter" ref="vendorAdaptor" />         
    <property name="packagesToScan" value="com.softech.ls360.integration.regulators.plcb.domain"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">10</prop>
            <prop key="hibernate.show_sql">true</prop>              
        </props>        
    </property>
</bean> 

同じファイルは moderns-spring.xml 用です

次に、両方のファイルを大損害の春に含めています

app-context.xml

<import resource="classpath:database/hibernate-context.xml"/>
<import resource="classpath:database/legacyJpa-context.xml"/>
<import resource="classpath:database/modernJpa-context.xml"/> 

<context:annotation-config/>
....

しかし、このデザインには1つの流れがあります。両方のマネージャーが含まれています。レガシーとモダン。つまり、dbManager Bean が初期化されると、両方が必要になります@PersistenceContext(unitName="legacy_emf"), @PersistenceContext(unitName="modern_emf")。私のデフォルトpersistence contextはモダンであるため @PersistenceContext(unitName="modern_emf")、Beanの初期化時にこの永続コンテキストのみを使用できるようにする必要があります。enum to legacy次に 、私が設定した場合、unitName="legacy_emf"これが利用可能になるはずです。あなたは私を手に入れましたか?

ありがとう

編集 2: ----------------------------------------------- ----------------------

以下のdbManagerクラスを変更しました

@Lazy
@Service("dbManager") 
@Repository
@Transactional
public class DatabaseManager {

    public enum EnumLmsPlateform {
        MODERN,
        LEGACY;
    }

    private EnumLmsPlateform lmsPlatform;

    public DatabaseManager() {

    }

    @PostConstruct
    public void init() {
        setLmsPlatform(EnumLmsPlateform.MODERN);
    }


    public EnumLmsPlateform getLmsPlatform() {
        return lmsPlatform;
    }

    public void setLmsPlatform(EnumLmsPlateform lmsPlatform) {
        this.lmsPlatform = lmsPlatform;
    }

    @ModernTx
    public List<Object> getModernResultSet(String query, Class<?> mappingClass) { 
        EntityManager modernEm = getEntityManagerFormBoundTransactionalThread();
        return getResultSet(modernEm, query, mappingClass);

    }

    @LegacyTx 
    public List<Object> getLegacyResultSet(String query, Class<?> mappingClass) { 
        EntityManager legacyEm = getEntityManagerFormBoundTransactionalThread();
        return getResultSet(legacyEm, query, mappingClass);
    } 

    @Transactional 
    public List<Object> getDefaultResultSet(String query, Class<?> mappingClass) { 
        EntityManager defaultEm = getEntityManagerFormBoundTransactionalThread();
        return getResultSet(defaultEm, query, mappingClass);
    }

    private List<Object> getResultSet(EntityManager em, String query, Class<?> mappingClass) {
        Query emQuery = em.createNativeQuery(query, mappingClass);  
        return  emQuery.getResultList();    
    }

    private EntityManager getEntityManagerFormBoundTransactionalThread(){
        Map<Object, Object>  map =   TransactionSynchronizationManager.getResourceMap();   
        for (Object value  :map.values()) {
            if(value instanceof EntityManagerHolder){       
                return ((EntityManagerHolder)value).getEntityManager();

            }  
        } 

        return null;  

    } //end of  getEntityManagerFormBoundTransactionalThread()  

} //end of class

私のテストクラス

public class TestDynamicJpa {

    String springXmlFile = "classpath:spring/app-context-xml.xml";

    GenericXmlApplicationContext springContext = SpringUtil.loadSpringContext(springXmlFile);

    List<Object> traineeList = getLegacyResultList(springContext);

    private List<Object> getLegacyResultList(GenericXmlApplicationContext springContext) throws Exception {

        DatabaseManager dbManager = springContext.getBean("dbManager", DatabaseManager.class);

        List<Object> resultList = dbManager.getLegacyResultSet(FIND_TRAINEE_LEGACY, LegacyTrainee.class);

        return resultList;

    } //end of getLegacyResultList()

} //end of class TestDynamicJpa

一つの質問。私がする時

List<Object> resultList = dbManager.getLegacyResultSet(FIND_TRAINEE_LEGACY, LegacyTrainee.class);

LegacyTransactionManager次に、マップから取得します。しかし、私がそうするなら

List<Object> resultList = dbManager.getDefaultResultSet(FIND_TRAINEE_LEGACY, LegacyTrainee.class);

次に、Map から取得するトランザクション マネージャー。LegacyまたはModern

また、この構成でも確認しました

 <import resource="classpath:database/hibernate-context.xml"/>
 <import resource="classpath:database/legacyJpa-context.xml"/>
 <!--  
 <import resource="classpath:database/ls360Jpa-context.xml"/> 
 -->

つまり、Jpa コンテキストを 1 つだけインポートすると、問題なく動作します :)。私の以前の@PersistenceUnit構成では、1つのファイルをコメントアウトするとエラーが発生します:)。

ありがとう :)

4

1 に答える 1