要访问2个数据库,我们使用了两个不同的事务管理器(每个都有自己的数据源):弹簧开关(不需要单交易行为)
第一个事务管理器:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
第二个事务经理:
<bean id="transactionManager2"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
在服务层,我们希望有一个得到一个ID,并返回一个DTO的方法。问题是DTO必须填充来自两个数据库的数据。
我们尝试第一种方法:
- FooDao:使用SessionFactory的(同transactionManager的)
- BarDao:使用sessionFactory2(同SessionFactory的作为transactionManager2)
有以下服务方法:
@Autowired
private FooDao fooDao;
@Autowired
private BarDao barDao;
@Transactional(value="transactionManager", readOnly=true)
public FooBarDto getFoo(int id) {
Foo foo = fooDao.get(id);
return createDto(foo);
}
@Transactional(value="transactionManager2", readOnly=true)
public FooBarDto createDto(Foo foo) {
Bar bar = barDao.get(foo.getId());
FooBarDto fooBarDto = new FooBarDto();
fooBarDto.setId(String.valueOf(foo.getId()));
fooBarDto.setA(String.valueOf(foo.getA()));
fooBarDto.setB(String.valueOf(foo.getB()));
fooBarDto.setC(String.valueOf(bar.getC()));
fooBarDto.setD(String.valueOf(bar.getD()));
return fooBarDto;
}
但在这种情况下我们在barDao方法中得到“没有找到当前线程的会话”错误。由于我们不需要对单个事务进行整个操作(并保持当前配置),因此我们不希望使用JTA。
我们尝试配置事务传播(使用Propagation.REQUIRES_NEW),但看起来只适用于来自同一管理器的事务。
我们可以改变这两个方法并从控制器调用它们(按顺序),但我们更愿意调用单一的服务方法来完成所有的工作。有没有办法达到预期的行为?
非常感谢Ricardo Veguilla!遵循您的建议,现在一切正常。让我感动的createDto方法到另一个服务(BarService)和自动装配它的第一个服务(FooService接口):
@Service
public class FooServiceImpl implements FooService {
@Autowired
private FooDao fooDao;
@Autowired
private BarService barService;
@Transactional(value="transactionManager", readOnly=true)
public FooBarDto getFoo(int id) {
Foo foo = fooDao.get(id);
return barService.createDto(foo);
}
}
和创建的BarService:
@Service
public class BarServiceImpl implements BarService {
@Autowired
private BarDao barDao;
@Transactional(value="transactionManager2", readOnly=true)
public FooBarDto createDto(Foo foo) {
FooBarDto fooBarDto = new FooBarDto();
if (foo != null) {
Bar bar = barDao.get(foo.getId());
fooBarDto.setId(String.valueOf(foo.getId()));
fooBarDto.setA(String.valueOf(foo.getA()));
fooBarDto.setB(String.valueOf(foo.getB()));
if (bar != null) {
fooBarDto.setC(String.valueOf(bar.getC()));
fooBarDto.setD(String.valueOf(bar.getD()));
}
}
return fooBarDto;
}
}