在 HSQLDB 上使用 Spring DBUnit 进行休眠和 Spring 数据 - 由于外键约束而无法删除
Posted
技术标签:
【中文标题】在 HSQLDB 上使用 Spring DBUnit 进行休眠和 Spring 数据 - 由于外键约束而无法删除【英文标题】:Hibernate and Spring Data with Spring DBUnit on HSQLDB - Unable to delete due to foreign key constraint 【发布时间】:2015-07-17 20:44:47 【问题描述】:我正在使用 Hibernate 和 Spring Data 对一个非常简单的域进行建模:
@Entity
public class User implements Serializable
private static final long serialVersionUID = -5501812656863255674L;
@Id
private String emailAddress;
@Column
private String forename;
@Column
private String surname;
@Column
@Enumerated(EnumType.STRING)
private UserRole role;
@OneToMany(cascade = CascadeType.ALL )
private List<Team> teams;
和
@Entity
public class Team implements Serializable
private static final long serialVersionUID = -3734641391628154428L;
private static final BigDecimal STARTING_BUDGET = new BigDecimal(100);
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(unique = true)
private String name;
然后,我在数据服务中有一个“updateUser”方法,该方法按其命名。这个想法是为了给一个用户添加一个团队,这个方法会被使用,并且级联会导致团队被持久化在数据库中。
@Override
public void updateUser(final User user) throws IntegrationException
if (userRepository.exists(user.getEmailAddress()))
userRepository.save(user);
else
throw new IntegrationException(IntegrationExceptionCode.USER_NOT_FOUND);
然后我使用 HSQLDB 数据库和 Spring DBUnit 对该方法进行单元测试,以设置初始数据库内容和预期的数据库内容:
初始数据库内容配置
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<User emailAddress="user1@test.com" forename="User" surname="One" role="MANAGER" />
<Player />
<User_Team />
<Team />
</dataset>
预期的数据库内容配置
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<User emailAddress="user1@test.com" forename="User" surname="One" role="MANAGER" />
<Player />
<Team id="1" name="Test Team" totalScore="0" status="INCOMPLETE" remainingBudget="100" />
<User_Team User_emailAddress="user1@test.com" Teams_id="1" />
</dataset>
然后我有两个测试:一个测试更新是否成功;一种测试尚未在系统中的用户无法更新的方法。
成功测试
@Test
@ExpectedDatabase("UserData-WithTeam.xml")
public void testUpdateUser_AddedTeam_Success() throws Exception
// arrange
final User user = UserTestDataBuilder.aManager(VALID_EMAIL_ADDRESS, "User", "One").withTeam().build();
// act
userDataService.updateUser(user);
// assert - done by @ExpectedDatabase annotation
“用户不存在”测试
@Test
public void testUpdateUser_AddedTeam_UserDoesNotExist() throws Exception
// arrange
thrownException.expect(IntegrationException.class);
thrownException.expect(CustomIntegrationExceptionMatcher.hasCode(IntegrationExceptionCode.USER_NOT_FOUND));
final User user = UserTestDataBuilder.aManagerWithEmailAddress(INVALID_EMAIL_ADDRESS).withTeam().build();
// act
userDataService.updateUser(user);
// assert
Assert.fail("Exception expected");
“成功”测试运行良好。但是,“失败案例”测试错误并出现以下错误:
java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: foreign key no action; FK_RVG5KHM9RO439HI17HPAUV5KG table: USER_TEAM
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.JDBCStatement.execute(Unknown Source)
at org.dbunit.database.statement.SimpleStatement.executeBatch(SimpleStatement.java:69)
at org.dbunit.operation.DeleteAllOperation.execute(DeleteAllOperation.java:126)
at org.dbunit.operation.CompositeOperation.execute(CompositeOperation.java:79)
at com.github.springtestdbunit.DbUnitRunner.setupOrTeardown(DbUnitRunner.java:194)
at com.github.springtestdbunit.DbUnitRunner.beforeTestMethod(DbUnitRunner.java:66)
at com.github.springtestdbunit.DbUnitTestExecutionListener.beforeTestMethod(DbUnitTestExecutionListener.java:186)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:249)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hsqldb.HsqlException: integrity constraint violation: foreign key no action; FK_RVG5KHM9RO439HI17HPAUV5KG table: USER_TEAM
at org.hsqldb.error.Error.error(Unknown Source)
at org.hsqldb.StatementDML.performReferentialActions(Unknown Source)
at org.hsqldb.StatementDML.delete(Unknown Source)
at org.hsqldb.StatementDML.executeDeleteStatement(Unknown Source)
at org.hsqldb.StatementDML.getResult(Unknown Source)
at org.hsqldb.StatementDMQL.execute(Unknown Source)
at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
at org.hsqldb.Session.executeDirectStatement(Unknown Source)
at org.hsqldb.Session.execute(Unknown Source)
... 32 more
这似乎是在暗示它不能拆除'success'测试中添加的测试数据(并且我已经在成功测试中添加了@Ignore注释并且失败测试通过了)。我的问题是为什么?我在 @OneToMany 关系上的级联设置为 ALL,因此应删除作为用户-团队关系一部分保存的所有实体。
有人有什么想法吗?
【问题讨论】:
【参考方案1】:我认为您在USER_TEAM
表中有一个完整性约束:UPDATE NO ACTION
这就是为什么给java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: foreign key no action;
【讨论】:
以上是关于在 HSQLDB 上使用 Spring DBUnit 进行休眠和 Spring 数据 - 由于外键约束而无法删除的主要内容,如果未能解决你的问题,请参考以下文章
如何在当前使用 HSQLDB 的 Spring 和 Hibernate 后台使用 MySQL
如何使用注解在 Spring JPA 中定义 HSQLDB 属性
使用 JavaConfig 使用 Spring 应用程序的 HSQLDB 新手
使用 HSQLDB 作为 Spring、Hibernate 的可移植数据库