要访问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必须填充来自两个数据库的数据。
我们尝试了第一种方法:
使用以下服务方法:
@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;
}
但是在这种情况下,我们得到了#34;当前线程没有找到会话&#34; barDao方法中的错误。由于我们不需要对单个事务进行整个操作(并保留当前配置),因此我们不希望使用JTA。
我们尝试配置事务传播(使用Propagation.REQUIRES_NEW),但看起来它只适用于来自同一经理的事务。
我们可以更改这两种方法并从控制器中调用它们(顺序),但我们更愿意调用单个服务方法来完成所有工作。有没有办法实现预期的行为?
非常感谢里卡多·韦吉拉!按照你的建议,现在一切正常。我将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;
}
}
答案 0 :(得分:1)
您在同一个bean内调用barDao
的{{1}} bacuse中没有会话,这意味着方法调用不会通过Spring Transacitional代理。
在Spring中,带有注释为createDto
的公共方法的bean myBean
需要从包含Spring注入@Transactional
实例的其他bean调用,因为事务支持已实现使用代理。您需要将myBean
方法移动到另一个bean:
createDto
答案 1 :(得分:0)
如果您使用Java 8,您可以创建类:
@Component
class TransactionWrapper {
@Transactional
public <T> T doInTransaction(Supplier<T> supplier) {
return
}
在事务上下文中调用类内的方法(即私有方法)。