2016-12-19 3 views
0

Я использую Hibernate 5.2.1 и 4.3.0 SpringСделать Hibernate неудачу на отсутствие сделки

Мое текущее понимание:

  • Hibernate требует активной транзакции базы данных для операций записи для надежной работы.
  • Если транзакции отсутствуют, режим сброса устанавливается на АВТО (по умолчанию), и режим автоматического фиксации не включен, спящий режим является довольно непредсказуемым. В зависимости от звонков .flush(), .clear(), .openSession()/.getCurrentSession() один Мощь
    • триггер на запись в базу данных
    • быть в состоянии прочитать объект .persist() ред который не является и не будут записаны в базу данных
    • молча теряет .persist() объекты под ред
    • написать некоторые объекты в базу данных, но не писать другие (при использовании, например, отношений)

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

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

Я подхожу к этому неправильно? Я что-то не понял?


Просто для справки:

ответ

1

Hibernate сообщество говорит, что работа за пределами сделки может привести к непредсказуемым результатам. Это связано с тем, что Hibernate откроет транзакцию, но она не будет закрыта сама по себе, поэтому соединение будет возвращено в пул соединений, при этом транзакция не будет выполнена. Что происходит тогда? JDBC сохраняет молчание, поэтому это специфично для реализации (MySQL откатывает транзакцию, Oracle afair ее совершает). Это также можно настроить на уровне пула соединений (например, C3P0 предоставляет вам такую ​​возможность, откат по умолчанию).

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

Вы должны установить порог протоколирования DEBUG для следующих классов:

  1. Для JDBC транзакций (например, RESOURCE_LOCAL)

    • Для SLF4J лесозаготовок:

      <logger name="org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction" level="debug"/> 
      
    • Для Log4j:

      <logger name="org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction"> 
          <level value="DEBUG"/> 
      </logger> 
      
  2. Для ССТ сделок

    • Для протоколирования SLF4J:

      <logger name="org.hibernate.engine.transaction.internal.jta.JtaTransaction" level="debug"/> 
      
    • Для Log4j:

      <logger name="org.hibernate.engine.transaction.internal.jta.JtaTransaction"> 
          <level value="DEBUG"/> 
      </logger> 
      

В журналах вы увидите следующие записи:

  • при запуске транзакции:

    DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - initial autocommit status: true 
    DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - disabling autocommit 
    
  • , когда транзакция завершается:

    DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - committed JDBC Connection 
    DEBUG [Alice]: o.h.e.t.i.j.JdbcTransaction - re-enabling autocommit 
    

Лучше активировать уровень DEBUG как можно меньше классов, потому что в противном случае размер ваших журналов резко возрастет.

Я подхожу к этому неправильно? Я что-то не понял?

Если вы можете забыть @Transactional в где-нибудь, попробуйте зимовать с autocommit=true которая выйдет из строя едва на тупых кодов и помнит вас. Или вы можете использовать aspectj, чтобы сделать все методы DAOs транзакционными.

Смежные вопросы