在缺少事务时使Hibernate失败

时间:2016-12-19 17:10:26

标签: spring hibernate transactions

我正在使用Hibernate 5.2.1和Spring 4.3.0

我目前的理解是:

  • Hibernate需要一个活动的数据库事务才能使写操作可靠地工作。
  • 如果没有事务,则刷新模式设置为AUTO(默认值),并且没有启用自动提交模式,休眠是相当不可预测的。可以根据对import os def get_next_run(path): id = 1 while(os.path.exists(path + "/run" + id)): id += 1 return path + "/run" + id .flush().clear() / .openSession()的来电
    • 触发对数据库的写入
    • 能够读取未写入和不会写入数据库的.getCurrentSession() ed对象
    • 默默地丢失.persist() ed对象
    • 将一些对象写入数据库,但无法编写其他对象(例如使用关系时)

我已经花了太多时间在不那么快乐的bug搜索中,最终在我身上发现我错过了.persist()注释,错过了配置合理的事务模式或者无法在Spring中配置事务管理器。 / p>

希望我的软件足够强大,可以告诉我什么时候我做了一些愚蠢的事情或忘记了某些事情,而不是只是默默地失败并陷入未定义的行为模式。

在错过交易时,是否有可能让hibernate大声抱怨?

我接近这个错误的方式吗?我误解了什么吗?

仅供参考:

1 个答案:

答案 0 :(得分:1)

Hibernate社区表示,在事务之外工作可能会导致不可预测的行为。这是因为Hibernate将打开事务,但它不会自己关闭它,因此连接将返回到连接池,而事务未被提交。那么会发生什么? JDBC保持沉默,因此这是特定于实现的(MySQL回滚事务,Oracle afair提交它)。这也可以在连接池级别配置(例如,C3P0为您提供了这样的选项,默认情况下为回滚)。

  

当它缺少一个时,是否有可能让hibernate大声抱怨   交易?

您需要为以下类设置日志记录阈值为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. 对于JTA交易

    • 对于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>
      
  3. 在日志中,您将看到以下条目:

      交易开始时
    • 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使所有DAO方法成为事务性的。