Подтвердить что ты не робот

Spring управляемые транзакции без аннотации @Transactional

Я использую аннотации 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 позволяет мне получать данные из базы данных даже без аннотации.

Каковы последствия такого рода небрежности и каковы наиболее вероятные сценарии, которые могут произойти?

4b9b3361

Ответ 1

В соответствии с документацией (Spring docs) это просто метаданные, чтобы дать указание, что метод или интерфейс могут быть настроены чем-то то есть "транзакционно известно" (т.е. <tx:annotation-driven/>).

С помощью только tx: привязанного к аннотациям и атрибута @Transactional, я считаю, что вы применяете транзакцию по умолчанию:

  • ТРЕБУЕТСЯ ПРОГРАММА РАЗМЕЩЕНИЯ.
  • Уровень изоляции DEFAULT.
  • Транзакция читается/записывается.
  • Тайм-аут транзакции по умолчанию соответствует тайм-ауту по умолчанию для базовой транзакционной системы или никому, если тайм-ауты не поддерживаются.
  • любое RuntimeException вызывает откат, и любое исключенное исключение не выполняет.

Предполагая, что вы используете <tx:annotation-driven />, чтобы управлять им через диспетчер транзакций, а затем пропускать атрибут @Transactional, значит вы не можете применять такие свойства, как readOnly, изоляция, распространение, rollbackFor, noRollbackFor и т.д.

Я считаю, что MVC немного отличается - сеанс Hibernate привязан непосредственно к запросу MVC, то есть когда запрос получен, транзакция начинается.

Вернемся к вашему примеру, код для getSession() в HibernateDAOSupport выглядит следующим образом:

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)

В сущности, транзакция: сеанс привязан 1:1 AFAIK, и единственный способ запуска без транзакции - использовать JBoss, который имеет "запеченный" уровень сохранения, который обеспечивает транзакцию для вас (под обложками), Даже если вы вызываете getQuery() после getSession(), вы по-прежнему эффективно выполняете транзакцию, являющуюся соединением JDBC/Hibernate.

Ответ 2

Без аннотации вы теряете преимущества транзакций, таких как откаты.

В аннотации @Transactional вы выполняете более одной операции с базой данных, например, многие вставки и один не удается, все операции в транзакции могут откатываться, чтобы обеспечить согласованность с вашими данными.

Именно поэтому рекомендуется поместить аннотацию в сервисы не в DAO.

Ответ 3

Ничего не произойдет, если вы не поместите аннотацию @transactional. В основном @Transactional не обязательно вводить верхнюю часть подписи метода, она просто используется для информирования компилятора, когда транзакция только для чтения = true (только для целей поиска данных ) и когда он только для чтения = false (только для операций удаления обновлений вставки)

Ответ 4

В вашем сценарии ваш DAO будет выполняться без транзакции, скорее всего, с автоматическим фиксацией.

Если вы хотите избежать такой ошибки в будущем и потребовать, чтобы все ваши службы выполнялись в транзакции, вы можете защитить слой DAO с помощью следующей аннотации @Transactional:

@Transactional(propagation = MANDATORY)
public class HibernateAlertDAO extends HibernateDaoSupport implements AlertDAO {
   ...
}

Эта аннотация требует, чтобы уровень сервиса объявлял транзакцию и в противном случае генерирует исключение.