JPA DBUnit HsqlDb:禁用约束检查?
JPA DBUnit HsqlDb: Disable constraint checks?
我的应用程序只从数据库中读取数据。没有 create/update/delete 操作。我正在尝试将一个数据库视图映射到 JPA 实体。此视图没有任何唯一 ID。所以基本上每一行都是独一无二的。但是有可能某些列的值可能为空。
现在的问题是:
1) 我无法对 database.Its 进行超出我的范围的任何更改。因此无法为唯一 ID 添加新列的视图。
2) 我无法在没有主键的情况下创建 JPA 实体,因为它会抱怨它至少需要一个唯一的键。
3) 如果我将@Id 注释应用于所有列,那么它在逻辑上是有意义的,因为每一行在我的例子中都是唯一的。但是在我的单元测试中,HSQLDB 会抱怨一些唯一的列可能没有空值。
4) 所以我决定defer/disable所有约束。因为在我的例子中,约束仅在使用 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 }
但是没有用。
更新二:
我尝试使用以下方法将这些列显式设置为空:
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]
两个可能有帮助的想法:
将具有复合主键的 JPA 实体映射到现有数据库时,@EmbeddedId 是实体与多个 @Id 字段的正确方法:
- 使用多个 @Id 字段创建第二个 class 并使用 @Embeddable 注释此 class。
- 在实体上创建第二种 class 类型的单个字段,用 @EmbeddedId 注释。
此外,由于它是在只读模式下使用的,因此在@Id 字段上使用可插入和可更新的@Column 属性:
@Column(可插入=假,可更新=假)
这些可能会导致 JPA 提供程序在唯一性问题上表现不同。
对于类似情况,我删除了 Apache Derby 的引用完整性约束。我认为它也适用于 HSQLDB。
您的问题没有说明您在什么时候发出删除约束命令,因此请确保您在每个需要删除约束的测试开始时发出它们。
我写了一个 "ConstraintManipulator" class 删除和恢复约束。需要禁用约束的测试在测试之前调用正确的 ConstraintManipulator remove 方法并在测试之后添加方法(只希望为某些测试关闭特定约束并为后续测试恢复它们)。这些方法只是使用 dbUnit 配置的 JDBC 数据库连接发出 DDL 命令("add constraint ..."、"drop constraint ...")。
我通过首先删除主键解决了这个问题:
ALTER TABLE T_NAME DROP PRIMARY KEY
然后使用以下方法删除各个列的非空约束:
ALTER TABLE T_NAME ALTER COLUMN C_NAME SET NULL
正如 Jeff 在他的回答中所建议的,单独编写 class 来禁用单个测试套件的约束是有意义的。
我的应用程序只从数据库中读取数据。没有 create/update/delete 操作。我正在尝试将一个数据库视图映射到 JPA 实体。此视图没有任何唯一 ID。所以基本上每一行都是独一无二的。但是有可能某些列的值可能为空。
现在的问题是:
1) 我无法对 database.Its 进行超出我的范围的任何更改。因此无法为唯一 ID 添加新列的视图。
2) 我无法在没有主键的情况下创建 JPA 实体,因为它会抱怨它至少需要一个唯一的键。
3) 如果我将@Id 注释应用于所有列,那么它在逻辑上是有意义的,因为每一行在我的例子中都是唯一的。但是在我的单元测试中,HSQLDB 会抱怨一些唯一的列可能没有空值。
4) 所以我决定defer/disable所有约束。因为在我的例子中,约束仅在使用 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 }
但是没有用。
更新二:
我尝试使用以下方法将这些列显式设置为空:
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]
两个可能有帮助的想法:
将具有复合主键的 JPA 实体映射到现有数据库时,@EmbeddedId 是实体与多个 @Id 字段的正确方法:
- 使用多个 @Id 字段创建第二个 class 并使用 @Embeddable 注释此 class。
- 在实体上创建第二种 class 类型的单个字段,用 @EmbeddedId 注释。
此外,由于它是在只读模式下使用的,因此在@Id 字段上使用可插入和可更新的@Column 属性: @Column(可插入=假,可更新=假)
这些可能会导致 JPA 提供程序在唯一性问题上表现不同。
对于类似情况,我删除了 Apache Derby 的引用完整性约束。我认为它也适用于 HSQLDB。
您的问题没有说明您在什么时候发出删除约束命令,因此请确保您在每个需要删除约束的测试开始时发出它们。
我写了一个 "ConstraintManipulator" class 删除和恢复约束。需要禁用约束的测试在测试之前调用正确的 ConstraintManipulator remove 方法并在测试之后添加方法(只希望为某些测试关闭特定约束并为后续测试恢复它们)。这些方法只是使用 dbUnit 配置的 JDBC 数据库连接发出 DDL 命令("add constraint ..."、"drop constraint ...")。
我通过首先删除主键解决了这个问题:
ALTER TABLE T_NAME DROP PRIMARY KEY
然后使用以下方法删除各个列的非空约束:
ALTER TABLE T_NAME ALTER COLUMN C_NAME SET NULL
正如 Jeff 在他的回答中所建议的,单独编写 class 来禁用单个测试套件的约束是有意义的。