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

Juk*_*nen 18 java spring hibernate transactions

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

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

     private AlertDAO alertDAO;

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

}
Run Code Online (Sandbox Code Playgroud)

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

// 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;
    }

}
Run Code Online (Sandbox Code Playgroud)

当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;
    }

}
Run Code Online (Sandbox Code Playgroud)

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

这种疏忽的后果是什么?可能发生的最坏情况是什么?

Al *_*man 9

根据文档(Spring文档),它只是元数据,表明方法或接口可以由"事务感知"(即<tx:annotation-driven/>)进行配置.

只有tx:annotation-driven和no @Transactional属性我相信你应用了"默认"事务性:

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

假设您正在使用<tx:annotation-driven />通过事务管理器驱动它,那么错过该@Transactional属性意味着您无法应用诸如readOnly,isolation,propagation,rollbackFor,noRollbackFor属性.

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

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

protected final Session getSession()
    throws DataAccessResourceFailureException, IllegalStateException 
{
    return getSession(this.hibernateTemplate.isAllowCreate());
}
Run Code Online (Sandbox Code Playgroud)

反过来要求:

/**
 * 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());
}
Run Code Online (Sandbox Code Playgroud)

最终要求:

/** 
 * ....
 * @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)
Run Code Online (Sandbox Code Playgroud)

从根本上说,一个事务:会话是1:1的AFAIK,并且没有事务运行的唯一方法是使用JBoss,它具有'烘焙'持久层,为您提供事务性(在封面下).即使您getQuery()getSession()仍然有效地发生事务之后调用,因为它是JDBC/Hibernate连接.