【发布时间】:2014-08-29 20:08:07
【问题描述】:
为了访问 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(与 transactionManager2 相同的 sessionFactory)
采用以下服务方式:
@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;
}
}
【问题讨论】:
标签: spring hibernate spring-transactions