2014-04-13 7 views
12

में एकाधिक लेनदेन प्रबंधकों के साथ एकाधिक डेटा स्रोत, जूनिट एप्लिकेशन संदर्भ फ़ाइल में परिभाषित तीन DataSource (जेडीबीसी) है। उनमें से दो को लेनदेन से प्रबंधित करने की आवश्यकता है; इन दो डेटा स्रोतों का उपयोग करते समय मुझे किसी भी विधि को श्रृंखलाबद्ध करने की आवश्यकता नहीं है (वे एक-दूसरे से पूरी तरह से स्वतंत्र हैं)।वसंत

मुझे कोई समस्या नहीं थी जब मैंने dataSource2 के लिए एक एकल लेनदेन प्रबंधक का उपयोग किया, भले ही dataSource3 का उपयोग किया जा रहा था लेकिन संबंधित विधियों में प्रबंधित नहीं किया गया था। फिर भी, विभिन्न डीएओ कक्षाओं से विधियों का प्रबंधन करने की आवश्यकता पर जो पूरी तरह से dataSource3 का उपयोग करते हैं, मैंने दूसरा लेनदेन जोड़ा - txManager2। प्रसंग फ़ाइल निम्नलिखित शामिल हैं:

<context:component-scan base-package="my.pkg" /> 

<bean id="dataSource1" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> 
    <property name="url" value="jdbc:oracle:thin:@host1:1521:dbsid1" /> 
<property name="username" value="username1" /> 
<property name="password" value="password1" /> 
</bean> 

<bean id="dataSource2" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> 
    <property name="url" value="jdbc:oracle:thin:@host2:1521:dbsid2" /> 
<property name="username" value="username2" /> 
<property name="password" value="password2" /> 
</bean> 

<bean id="dataSource3" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> 
    <property name="url" value="jdbc:oracle:thin:@host3:1521:dbsid3" /> 
<property name="username" value="username3" /> 
<property name="password" value="password3" /> 
</bean> 

<tx:annotation-driven/> 

<bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <qualifier value="txManager1"/> 
<property name="dataSource2" ref="dataSource2"/> 
</bean> 

<bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <qualifier value="txManager2"/> 
<property name="dataSource3" ref="dataSource3"/> 
</bean> 

के बाद से कई लेन-देन प्रबंधकों परिभाषित किया जा रहा है, अपने स्वयं के मूल्यों के साथ मैं योग्य उन्हें। आप देख सकते हैं, dataSource3 एक सेटर विधि का उपयोग इंजेक्शन जा रहा है:,

package my.pkg; 

@Component 
public class MyDAO { 

    private DataSource dataSource3; 

    // Read only from datasource 
    @Autowired 
    @Qualifier("dataSource") 
    public void setDataSource(DataSource ds) { 
     template = new NamedParameterJdbcTemplate(ds); 
    } 

    // Performs reads/updates/inserts from datasource2 
    @Autowired 
    @Qualifier("dataSource2") 
    public void setDataSource2(DataSource ds) { 
     iTemplate = new NamedParameterJdbcTemplate(ds); 
    } 

    // Performs reads/updates/inserts from datasource3 
    @Autowired 
    @Qualifier("dataSource3") 
    public void setDataSource3(DataSource ds) { 
     dataSource3 = ds; 
     uTemplate = new NamedParameterJdbcTemplate(ds); 
    } 

    @Transactional("txManager1")  
    public String insertProcs() { } 

    @Transactional("txManager2")  
    public String updateProcs() { } 
} 

हालांकि JUnit इकाई परीक्षण चल पर, मैं निम्नलिखित मिल:

java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) 
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txManager2' defined in class path resource [test-context.xml]: 

Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'dataSource3' of bean class 

[org.springframework.jdbc.datasource.DataSourceTransactionManager]: Bean property 'dataSource3' is not writable or has an invalid setter method. Does the parameter 

type of the setter match the return type of the getter? 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1363) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1085) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:516) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455) 
     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293) 
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290) 
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192) 
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585) 
     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895) 
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425) 
     at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84) 
     at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1) 
     at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280) 
     at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304) 
     ... 24 more 
    Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'dataSource3' of bean class 

    [org.springframework.jdbc.datasource.DataSourceTransactionManager]: Bean property 'dataSource3' is not writable or has an invalid setter method. Does the parameter 

    type of the setter match the return type of the getter? 
     at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1052) 
     at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:921) 
     at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76) 
     at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360) 

किसी भी विचार जहां के स्रोत यह समस्या है?

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

<bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <qualifier value="txManager1"/> 
    <property name="dataSource" ref="dataSource2"/> 
</bean> 

<bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <qualifier value="txManager2"/> 
    <property name="dataSource" ref="dataSource3"/> 
</bean> 

@Qualifier("dataSource") को सही किया जाना चाहिए था (मेरी ओर से टाइपो):

अद्यतन

जवाब स्वीकार किए जाते हैं के आधार पर, निम्न परिवर्तन का इरादा कार्यक्षमता प्राप्त करने के लिए किए गए थे

// Read only from datasource 
    @Autowired 
    @Qualifier("dataSource1") 
    public void setDataSource1(DataSource ds) { 
     template = new NamedParameterJdbcTemplate(ds); 
    } 

उत्तर

9

आपकी कॉन्फ़िगरेशन के साथ कुछ समस्याएं हैं:

<property name="dataSource2" ref="dataSource2"/> 
<property name="dataSource3" ref="dataSource3"/> 

बीन नाम अलग हैं, लेकिन संपत्ति के नाम नहीं हैं। क्रमशः txManager1 और txManager2 सेम के लिए सेटर गुण में

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

उदा .:: आप को यह बदलना चाहिए।

दूसरा: @Qualifier("dataSource2") और @Qualifier("dataSource3") गलत हैं क्योंकि आप TX प्रबंधक बीन्स को अर्हता प्राप्त कर रहे हैं, न कि डेटा-स्रोत बीन्स।

आप इसके बजाय @Resource("dataSource2") और @Resource("dataSource3") का उपयोग कर सकते हैं, या डेटा-स्रोत बीन्स को भी अर्हता प्राप्त कर सकते हैं।

तीसरा: @Qualifier("dataSource")। सूचना यह या तो एक क्वालीफायर और एक सेम के नाम के साथ शिकायत नहीं है (ध्यान दें: यह dataSource1 है)

एक आखिरी बात के रूप में, आप tx:annotation-driven को परिभाषित किया है। यह एक लेनदेन प्रबंधक की अपेक्षा करता है जिसका बीन नाम लेनदेन प्रबंधक है। आप इसे बीन परिभाषा भी देने में असफल रहे हैं, इसलिए यह असफल हो जाएगा।

+0

संपत्ति का नाम मुद्दा था, और मैं 'टीएक्स: एनोटेशन-संचालित 'में पहला लेनदेन शामिल करना भूल गया था। 'डेटासोर्स' क्वालीफायर गलती एक टाइपो थी (मैं इसे प्रश्न में छोड़ रहा हूं इसलिए प्रदान किया गया उत्तर भावी पाठकों के लिए जगह से बाहर नहीं होगा)। – Malvon

+0

मेरे लिए काम किया। धन्यवाद दोस्तों। – Shashank

+0

क्लासिक स्पष्टीकरण :) –