Tôi có ba DataSource
(JDBC) được định nghĩa trong tệp ngữ cảnh ứng dụng Junit. Hai trong số họ cần được quản lý giao dịch; Tôi không phải kết nối bất kỳ phương pháp nào khi sử dụng hai nguồn dữ liệu này (chúng hoàn toàn độc lập với nhau).Nhiều nguồn dữ liệu với nhiều người quản lý giao dịch trong mùa xuân
Tôi không gặp sự cố khi tôi sử dụng một người quản lý giao dịch duy nhất cho dataSource2
, mặc dù dataSource3
đã được sử dụng nhưng không được quản lý theo các phương pháp tương ứng. Tuy nhiên, khi cần quản lý các phương thức từ các lớp DAO khác nhau chỉ sử dụng dataSource3
, tôi đã thêm giao dịch thứ hai - txManager2
. Các tập tin bối cảnh chứa thông tin sau:
<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>
Kể từ khi nhiều nhà quản lý giao dịch đang được xác định, tôi có trình độ chúng với các giá trị của riêng mình. Như bạn có thể thấy, dataSource3
đang được tiêm sử dụng một phương pháp setter:
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() { }
}
Tuy nhiên, khi chạy các đơn vị kiểm tra Junit, tôi nhận được như sau:
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)
Bất kỳ ý tưởng nơi khởi nguồn của vấn đề là?
Cập nhật
Dựa trên câu trả lời được chấp nhận, các thay đổi sau đã được thực hiện để có được những chức năng dự định:
<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")
nên đã được sửa chữa (typo trên một phần của tôi):
// Read only from datasource
@Autowired
@Qualifier("dataSource1")
public void setDataSource1(DataSource ds) {
template = new NamedParameterJdbcTemplate(ds);
}
Tên thuộc tính là vấn đề và tôi đã quên bao gồm giao dịch đầu tiên trong 'tx: chú thích định hướng'. Sai lầm vòng loại 'dataSource' là một lỗi đánh máy (tôi để nó trong câu hỏi để câu trả lời được cung cấp sẽ không bị lỗi cho người đọc trong tương lai). – Malvon
Làm việc cho tôi. cảm ơn các bạn. – Shashank
Giải thích cổ điển :) –