【问题标题】:Unable to generate constraint violation exception when testing Hibernate @Check constraints测试 Hibernate @Check 约束时无法生成约束冲突异常
【发布时间】:2019-04-13 17:14:54
【问题描述】:

我正在使用 Hibernate @Check 注释,但在不满足约束时不能让我的测试失败。目前只是使用带有 H2 数据库的默认 Spring boot 配置。

我错过了什么? save(..) 之后应该有某种 flush 吗?

运行测试时,我看到表创建正确。如果我从日志中复制创建行并使用它为我的“真实”Postgres 数据库创建一个表,我可以测试不同的插入,并看到该行在约束条件下一切正常。

实体

@Getter @Setter
@Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
public class Constrained {

    @Id @GeneratedValue
    private Long id;

    private String a, b;
}

测试

@DataJpaTest
@RunWith(SpringRunner.class)
public class HibernateCheckTest {

    @Resource // this repo is just some boiler plate code but attached at 
              // the bottom of question
    private ConstrainedRepository repo;

    @Test @Transactional // also tried without @Transactional
    public void test() {
        Constrained c = new Constrained();
        repo.save(c); // Am I wrong to expect some constraint exception here?
    }
}

运行测试时的表格生成脚本

创建表受限(id bigint 不为空,a varchar(255),b varchar(255), 主键 (id), 检查 (a IS NOT NULL OR b IS NOT 空))

Repository(在 repo 中没什么可看的,只是为了展示它):

public interface ConstrainedRepository
            extends CrudRepository<Constrained, Long> {
}

但是

如果我使用EntityManager,那么添加到我的测试类中:

@PersistenceContext
private EntityManager em;

并像这样坚持:

em.persist(c);
em.flush();

而不是repo.save(c) 我会得到异常。

使用repo.save(c) 更仔细地研究原始测试的日志:

org.springframework.test.context.transaction.TransactionContext:139 - 为测试回滚事务:
...
testException = [null],

所以由于某种原因,这个错误只是被包装和记录了。使用存储库进行持久化时如何将其“解包”并抛出?

【问题讨论】:

    标签: java hibernate spring-boot jpa h2


    【解决方案1】:

    ConstrainedRepository 中,扩展JpaRepository 而不是CrudRepository,然后使用:

    repo.saveAndFlush(c);
    

    代替:

    repo.save(c);
    

    检查是在数据库中执行的,并且仅在将更改(在本例中为 INSERT 语句)刷新到数据库时才会发生。

    在没有显式刷新的情况下,Hibernate will defer 将语句发送到数据库,直到提交事务或执行查询。

    但是,来自 Spring DataJpaTest 文档:

    默认情况下,数据 JPA 测试是事务性的,并在最后回滚 每次测试。

    所以,在这种情况下,没有提交。事务回滚,语句永远不会刷新到数据库,因此永远不会抛出异常。

    【讨论】:

    • 谢谢。我会假设这样的事情。我在一些问答中看到过这种方法,但我现在的问题是我的回购不包含这种方法?我应该构建 myt repo 还是以不同的方式进行测试? (我也在浏览文档,但如果你知道快速回答)
    • 啊,对不起,该方法在 JpaRepository 但不在 CrudRepository 中。已更新我的答案。
    【解决方案2】:

    感谢来自 codemonkeyanswer,我能够找到解决方案。这可以通过添加:

    @org.springframework.transaction.annotation.Transactional(propagation = 
                                                         Propagation.NOT_SUPPORTED)
    

    到我的测试班。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多