【问题标题】:issue with spring transaction management?春季交易管理问题?
【发布时间】:2012-08-10 15:52:52
【问题描述】:

我正在使用弹簧和休眠。我正在使用 spring 进行事务管理。我有以下课程。

@Service
@Transactional(readOnly = true)
public class Sample implements SampleInterface{

@Override
public List<Some> getData(){

//gets data after that it updates something

setStatus(someId);

}

@Override
@Transactional
public void setStatus(Long someId){

//sets status

}

}

如果我不为 getData() 保留 @Transactional,那么我会遇到异常。

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode

如果我为 getData() 保留@Transactional,那么它将正确保存。这里有什么问题?我如何为 setStatus() 提供 @Transactional。我仍然需要为 getData() 保留@Transactional,因为它正在调用一个将设置状态的公共方法?

谢谢!

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    问题有点复杂,是调用setStatus()insidegetData()引起的。当您从外部调用getData() 时,实际上是在调用Spring 框架为您创建的Java 代理。此代理应用事务行为(启动只读事务)并委托给您的实际服务类。这很好用。

    但是,当您调用 setStatus() 时,您将绕过事务代理并直接调用您的服务。换句话说,对setStatus() 的请求没有被拦截,@Transactional 被忽略

    没有简单的方法来处理这个问题, 也有同样的问题。在同一个类中调用公共方法时需要格外小心。

    另见

    【讨论】:

    • 感谢您的回复。如果我为 getData() 保留@Transactional,那么我的问题就解决了。这是一个好习惯吗?
    • @user1016403:这不是最好的方法,但我没有找到更好的方法。您可以提取setStatus(),但它不会解决您的特定问题。
    【解决方案2】:

    当您调用 getData(方法上没有 @Transactional)时,Spring 将启动一个只读事务,因为这是您的类的默认设置,而当 getData 调用 setStatus 时,Spring 将使用现有的 rad only 事务而不是创建新事务。这就是您收到异常的原因。

    默认的事务传播是 PROPAGATION REQUIRED。在http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#tx-propagation 阅读有关该主题的更多信息

    【讨论】:

    • 恕我直言,在这种特殊情况下,@Transactional 注释被完全忽略。即使使用REQUIRES_NEW 传播也会产生相同的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    相关资源
    最近更新 更多