【问题标题】:Why database contraints in HSQLDB are only checked during a commit when using transactions in Hibernate?为什么在 Hibernate 中使用事务时,仅在提交期间检查 HSQLDB 中的数据库约束?
【发布时间】:2016-04-11 23:11:31
【问题描述】:

我在 HSQL 中发现了一个奇怪的行为,似乎在使用数据库事务时,在 SQL 插入期间不检查数据库约束,但在 SQL 提交期间,当事务回滚时,根本不检查它们。

我有一个 Spring 集成测试:

@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=true, transactionManager="transactionManager")
@Transactional
public class IntegrationTest {

使用创建新实体实例并在其上调用 Hibernate 的 persist 的测试。

它工作正常,但是当我将 defaultRollback 更改为 false 时它失败了:

Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener@517a2b0] to process 'after' execution for test: method [public void MyIntegrationTest.test()], instance [MyIntegrationTest@546e61d5], exception [null]
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
  at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:161)
  at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:681)
  at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:563)
  at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
  at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
...
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10120 table: MYTABLE column: MYCOLUMN

这似乎是正确的,因为在调用persist 之前,我的代码确实没有在实体中设置 mycolumn 属性。

问题:

  • 为什么在插入期间而不是在提交期间检查数据库约束?
  • 为什么在回滚时不检查数据库约束?

【问题讨论】:

  • 由于 HSQLDB 没有延迟约束,因此在您运行插入或更新语句时会检查它们。我的猜测是您的混淆层(又名“ORM”)不会立即发送这些语句,而是稍后在您尝试提交时发送。当然,在回滚事务时检查约束是没有意义的,因为所有导致约束失败的更改都已撤消,所以没关系。
  • @a_horse_with_no_name 这是可能的,因为当我启用查询记录并使用defaultRollback=false 运行测试时,没有记录任何查询,而当我使用defaultRollback=false 运行它时,查询会被记录。跨度>
  • @a_horse_with_no_name 是的,我认为你是对的。在我可爱的休眠功能看来,插入和更新直到提交或非缓存实体上的 SELECT 才会发送。非常感谢!
  • 当使用 ORM 时,查询只会在提交时刷新到数据库(这是可配置的)。当没有发出查询时,没有什么要测试的。完成回滚后,没有任何内容被刷新,并且再次没有要测试的内容。

标签: java spring hibernate hsqldb


【解决方案1】:

[发布@a_horse_with_no_name 的答案,只是为了能够结束这个问题]。

在提交之前,我的 ORM(休眠)不会向数据库发送查询。如果事务以回滚结束,则根本不会将查询发送到数据库。确保在每个 persis() 修复问题后调用 flush() (FlushMode.ALWAYS)。

【讨论】:

    猜你喜欢
    • 2011-02-20
    • 2023-03-24
    • 2021-01-17
    • 2017-03-03
    • 2015-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    相关资源
    最近更新 更多