Весна совершает, когда не должно? (относится к Oracle autocommit) - PullRequest
3 голосов
/ 24 июня 2010

У меня есть интерфейс, подобный приведенному ниже

public interface FooDAO {
  public void callA(String x);
}

, и реализация, представленная ниже, намеренно делающая readonly true и не поддерживаемой

public class FooDAOImpl implements FooDAO {

  //for testing
  @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED) 
  public void callA(String x) {
     //sql update method
  }
}

В моем весеннем контексте я объявил менеджер транзакций источника данныхи tx: управляемый аннотациями.Я написал тест Junit4, который выглядит как

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(...)
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
public class MyTest {

    @Resource
    FooDAO fooDAO;

    @Test
    public void testRegisterWorker() {
        fooDAO.callA("")
    }
}

Я бы ожидал, что запись вообще не будет вставлена ​​в базу данных.Однако я вижу, что строка была вставлена ​​в БД.Я использую базу данных Oracle, так что я думаю, что для автоматической фиксации по умолчанию установлено значение true (я думаю).Но не должны ли весенние транзакционные теги переопределить их?

Может кто-нибудь сказать мне, что здесь происходит не так?

Ответы [ 3 ]

4 голосов
/ 24 июня 2010

Автокоммит, вероятно, включен по умолчанию. С DataSourceTransactionManager автокоммит изменяется только , если транзакция фактически запущена. Ни NOT_SUPPORTED, ни SUPPORTS не запускают транзакцию, поэтому при любом состоянии по умолчанию, в котором находится Соединение, оно останется.

Попробуйте отключить автоматическую фиксацию по умолчанию в XML-файле Spring. Если он включен, Spring должен будет изменить его перед каждой передачей и затем восстановить, что может быть дорого в Oracle (не уверен). Это также предотвращает случайное совершение транзакции за пределами транзакции.

Подробнее см. org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(), который управляет автоподстройкой и уровнем изоляции Соединения. doBegin () вызывается только AbstractPlatformTransactionManager.getTransaction() и handleExistingTransaction(), если распространение требуется, REQUIRES_NEW или PROPAGATION_NESTED.


Вы, вероятно, хотите взглянуть на org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests. Это базовый класс с поддержкой Spring, который вы можете использовать для своих тестовых классов. Он будет откатывать любые транзакции в конце каждого теста. Таким образом, нет необходимости изменять аннотации только для проверки. Вы можете установить свой @Transactional таким, каким он должен быть в prod, и полагаться на откаты, чтобы убедиться, что на самом деле ничего не изменилось в БД во время теста.

0 голосов
/ 24 июня 2010

Чтобы использовать @TransactionConfiguration, вы должны аннотировать либо ваш тестовый класс, либо метод теста @Transactional.Также ваш метод DAO, вероятно, выполняется без транзакции из-за propagation = Propagation.NOT_SUPPORTED.

0 голосов
/ 24 июня 2010

Autocommit - это «функция» JDBC, а не Oracle (в Oracle все операторы DML являются частью транзакции и, следовательно, фиксируются только тогда, когда приложение выдает коммит).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...