JPA DBUnit HsqlDb:禁用约束检查?

时间:2016-10-21 11:27:18

标签: java jpa hsqldb unique-constraint dbunit

我的应用程序仅从数据库中读取数据。没有创建/更新/删除操作。我试图将一个DB视图映射到JPA实体。此视图没有任何唯一ID。所以基本上每一行都是独特的。但是有些列的值可能为空。

现在的问题是:

1)我无法对数据库进行任何更改。它超出了我的范围。因此,无法使用新列添加视图以获取唯一ID。

2)我无法在没有主键的情况下创建JPA实体,因为它会抱怨它至少需要一个唯一的密钥。

3)如果我将@Id注释应用于所有列,那么它在逻辑上是有意义的,因为在我的情况下每一行都是唯一的。但在我的单元测试期间,HSQLDB会抱怨某些唯一列可能没有空值。

4)所以我决定推迟/禁用所有约束。因为在我的情况下,仅在使用DBUnit和HsqlDb创建内存模式期间考虑约束。

我尝试执行以下准备好的声明:

SET CONSTRAINTS ALL DEFERRED

但它失败了,错误:

Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: CONSTRAINTS

我不确定在初始数据库初始化期间如何禁用约束检查。我已经使用以下方法禁用了外键检查:

SET DATABASE REFERENTIAL INTEGRITY FALSE

它没有任何问题。如果您对如何禁用HsqlDb的所有约束检查有任何想法,请告诉我。

Jar版本:

DbUnit - 2.5.0

Junit - 4.10

HsqlDb 2.3.0

JDK - 1.7

更新1:

我将我的HsqlDb jar版本更新为2.3.4。我找到了以下参考资料:

http://hsqldb.org/doc/guide/dbproperties-chapt.html#N155DE

然后我尝试在最初的连接上执行这些语句:

SET DATABASE SQL UNIQUE NULLS { TRUE | FALSE }

但它没有帮助。

更新2:

我尝试使用以下方法将这些列显式设置为null:

ALTER TABLE T_NAME ALTER COLUMN C_NAME SET NULL

但我得错误说:

column is in primary key in statement [ALTER TABLE T_NAME ALTER COLUMN C_NAME SET NULL]

2 个答案:

答案 0 :(得分:1)

两个可能有所帮助的想法:

  1. 将具有复合主键的JPA实体映射到现有数据库时,@ EmbeddedId是实体与多个@Id字段的正确方法:

    1. 使用多个@Id字段创建第二个类,并使用@Embeddable注释此类。
    2. 在实体上创建第二个类类型的单个字段,使用@EmbeddedId注释。
    3. 此外,由于它以只读模式使用,因此请在@Id字段上使用可插入和可更新的@Column属性: @Column(insertable = false,updatable = false)

      这些可能会导致JPA提供商在唯一性问题方面表现不同。

    4. 对于类似情况,我使用Apache Derby删除了参照完整性约束。我认为它也适用于HSQLDB。

      您的问题并未说明您在何时发出删除约束命令,因此请确保在每次需要删除约束的测试开始时发出它们。

      我写了一个" ConstraintManipulator"删除和恢复约束的类。需要约束禁用的测试称为正确的ConstraintManipulator在测试之前删除方法并在测试之后添加方法(仅需要关闭某些测试的特定约束并将其恢复以用于后续测试)。这些方法只是使用dbUnit配置的JDBC数据库连接发出DDL命令("添加约束..."," drop constraint ...")。

      < / LI>

答案 1 :(得分:0)

我首先使用以下方法删除主键来解决此问题:

ALTER TABLE T_NAME DROP PRIMARY KEY

然后使用以下方法删除各列的非空约束:

ALTER TABLE T_NAME ALTER COLUMN C_NAME SET NULL

正如杰夫在他的回答中所建议的,编写单独的类来禁用各个测试套件的约束是有意义的。