一尘不染

没有@Transactional批注的Spring托管事务

hibernate

我正在使用Spring注释来管理我的事务,如下所示:

@Transactional(readOnly = true)
public class AlertServiceImpl implements AlertService {

     private AlertDAO alertDAO;

     public List<Alert> getAlerts(){
         List<Alert> alerts = alertDAO.getAlerts();
         return alerts;
     }

}

我想知道如果忘记注释会发生什么:

// Oops! Forgot to use transactional annotation 
public class AlertServiceImpl implements AlertService {

    private AlertDAO alertDAO;

    public List<Alert> getAlerts(){
         List<Alert> alerts = alertDAO.getAlerts();
         return alerts;
    }

}

当alertDAO实现如下时:

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

// no annotation here either
public class HibernateAlertDAO extends HibernateDaoSupport implements AlertDAO {

    public List<Alert> getAlerts(){
         // some implementation details that define queryString

         Query query = getSession().createQuery(queryString);
         List<Alert> alerts = query.list();

         return alerts;
    }

}

似乎Hibernate允许我从数据库中获取数据,即使没有注释也是如此。

这种粗心大意的后果是什么?可能发生的最坏情况是什么?


阅读 254

收藏
2020-06-20

共1个答案

一尘不染

根据文档(Spring
docs
),它仅仅是元数据,它表明方法或接口可以由“具有交易意识的”事物(例如<tx:annotation- driven/>)进行配置。

相信只有 tx:annotation驱动 并且没有@Transactional属性,我相信您可以应用“默认”事务性:

  • 传播设置是 必需的
  • 隔离级别为 DEFAULT
  • 事务是读/写。
  • 事务超时默认为基础事务系统的默认超时,如果不支持超时,则默认为无。
  • 任何 RuntimeException都会 触发回滚,而任何选中的 Exception 都不会触发。

假设您使用的<tx:annotation-driven />是通过事务管理器来驱动它,那么缺少该@Transactional属性意味着您无法应用诸如
readOnlyisolationpropagationpropagationrollbackFor
noRollbackFor属性

我相信MVC稍有不同-Hibernate会话直接与MVC请求绑定-即,当收到请求时,事务开始。

回到您的示例,HibernateDAOSupport中的getSession()的代码如下:

protected final Session getSession()
    throws DataAccessResourceFailureException, IllegalStateException 
{
    return getSession(this.hibernateTemplate.isAllowCreate());
}

依次调用:

/**
 * Obtain a Hibernate Session, either from the current transaction or
 * a new one. The latter is only allowed if "allowCreate" is true.
 *.......
 */
protected final Session getSession()
    throws DataAccessResourceFailureException, IllegalStateException {
    return getSession(this.hibernateTemplate.isAllowCreate());
}

最终要求:

/** 
 * ....
 * @param allowCreate whether a non-transactional Session should be created
 * when no transactional Session can be found for the current thread
 * ....
 */
private static Session doGetSession(
    SessionFactory sessionFactory, Interceptor entityInterceptor,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)

从根本上讲,Transaction:Session绑定为1:1
AFAIK,并且没有事务运行的唯一方法是使用说JBoss,它具有“嵌入”持久层,为您(在幕后)提供了事务性。即使您在调用getQuery()之后getSession()仍然有效地发生了事务,因为它是JDBC
/ Hibernate连接。

2020-06-20