Spring + Hibernate + Postgresql readOnly Transaction,按需保存

时间:2011-12-19 23:45:11

标签: hibernate spring postgresql

我有这种非标准情况,我需要在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'对象,不应保存。 我需要读取方法的原因是我在代码中加载了更多的对象:)滚动它们是我想做的最后一件事。

有可能这样做吗?

1 个答案:

答案 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中,但我认为这一点可以承担))