我有这种非标准情况,我需要在readOnly Hibernate事务中更新对象。问题是,我加载了许多其他对象,在该事务中更改它们,但只保存一个,休息滚动支持。我正在使用的数据库是Postgresql 8.4
我不确定我是否正确理解了文档,但提出了一种服务方法:
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
应该导致为该保存明确打开新的RW事务。
最重要的是,这不起作用:
@Transactional(readOnly = true)
public class PersonService {
@Resource(name="sessionFactory")
private SessionFactory sessionFactory;
public void add(Person person){
person.setFirstName("changed its name");
save(person);
}
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void save(Person person) {
Session session = sessionFactory.getCurrentSession();
session.save(person);
session.flush();
}
}
之后我得到了
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
从控制器中,调用'add'方法。 'add'处于readOnly模式,它将Person对象传递给'save'方法,该方法应该打开新的Transaction并保存到DB。在我的'add'方法项目中,我加载了许多其他'Person'对象,不应保存。 我需要读取方法的原因是我在代码中加载了更多的对象:)滚动它们是我想做的最后一件事。
有可能这样做吗?
答案 0 :(得分:2)
通常通过为服务接口生成实现来应用事务(您没有表明您正在实现一个接口,可能只是您的示例代码?)
无论如何,关键在于,在这种情况下,简单地调用save(...)不会通过包装器,它只是在目标对象上运行方法。您需要从服务注入一个引用,因此它可以调用自身并应用包装。那就是:
public class PersonServiceImpl implements PersonService {
PersonService personService;
public void readOnlyMethod() {
// ...
personService.readWriteMethod(...);
}
public void readWriteMethod(...) {
}
}
调用堆栈看起来像:
PersonServiceImpl.readWriteMethod(...)
TransactionAroundAdvice.advise(...) // starts/ends new read-write transaction
$Proxy.readWriteMethod(...) // implementing PersonService
PersonServiceImpl.readOnlyMethod(...)
TransactionAroundAdvice.advise(...) // starts/ends read-only transaction
$Proxy.readOnlyMethod(...) // implementing PersonService
ClientCode.doSomethingNotReallyReadOnly(...)
(您所描述的内容听起来像是记录了某种类型的错误消息,这是我使用过的必需新事务标记(尽管在J2EE中,但我认为这一点可以承担))