【问题标题】:Hibernate trying to delete foreign key row in spring休眠尝试在春季删除外键行
【发布时间】:2016-03-05 14:59:29
【问题描述】:

我正在尝试使用 spring hibernate/jpa 中的 crudRepository 删除操作从数据库中删除一个实体。实体(用户)与其他实体(组织)具有@OnetoMany 关系。删除用户时,它还会尝试删除与组织表中的外键对应的行,此时会引发错误。

我不想删除组织表中的行,只想删除用户userRepository.delete(createdUser);。谁能告诉我为什么这没有按预期工作?

User.java

/**
 * The user's organisation
 */
@NotNull
@SerializedName("organisation")
@Expose
@ManyToOne
@JoinColumn(name = "organisation_id")
private Organisation organisation;

Organisation.java

/**
 * The organisation's domain name
 */
@NotNull
private String domainName;

@OneToMany(mappedBy = "organisation")
private Set<User> users;

用户服务测试

@Test
public void create_SaveUserNewEntryToDatabase_ShouldReturnSingleUser() throws UserExistsException {
    long numberOfDbEntries = userRepository.count();
    User newUser = new User("jane@ibmtest.com", "Jane", "Claire", "Jones", new Long(98765), new Long(54321));
    User createdUser = userService.create(newUser);

    assertNotNull(createdUser);
    assertEquals(numberOfDbEntries+1, userRepository.count());
    assertEquals(createdUser.getFirstName(), "Jane");
    assertEquals(createdUser.getMiddleName(), "Claire");
    assertEquals(createdUser.getLastName(), "Jones");
    assertEquals(createdUser.getEmail(), "jane@ibmtest.com");
    assertEquals(createdUser.getOrganisation(), new Long(98765));
    assertEquals(createdUser.getUserRole(), new Long(54321));

    userRepository.delete(createdUser);  <------
    assertEquals(numberOfDbEntries, userRepository.count());
}

堆栈跟踪

org.dbunit.DatabaseUnitException: Exception processing table name='user'
    at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:232)
    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:265)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    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:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`watchmaker_db`.`user`, CONSTRAINT `FK_t2c7mdyen6pg5d1hpwyw6ox4e` FOREIGN KEY (`organisation_id`) REFERENCES `organisation` (`id`))
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
    at com.mysql.jdbc.Util.getInstance(Util.java:387)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1192)
    at org.dbunit.database.statement.SimplePreparedStatement.addBatch(SimplePreparedStatement.java:80)
    at org.dbunit.database.statement.AutomaticPreparedBatchStatement.addBatch(AutomaticPreparedBatchStatement.java:70)
    at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:214)
    ... 25 more

【问题讨论】:

  • 异常是 DBUnit 异常,从 setup 方法抛出。它不是由您的测试方法抛出的。
  • 但它是由 Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 无法添加或更新子行: 外键约束失败 (watchmaker_db.user,约束FK_t2c7mdyen6pg5d1hpwyw6ox4e外键(organisation_id)参考organisationid))
  • 我不认为异常是由您描述的问题引起的。为什么不在 hibernate 配置中激活 SQL 日志记录,并在测试中查看 Hibernate 有效执行了哪些 SQL 语句?
  • 由 DBUnit.beforeTestMethod 引起...所以它在设置中,而不是在测试中。堆栈跟踪再清楚不过了,所以看看你的 setup() 发出了什么 SQL 的日志。

标签: java spring hibernate jpa


【解决方案1】:

好吧,我希望测试能够正常工作,因为您使用的是foreign key。我在尝试使用 HSQLDB 时工作过,它也有限制,所以我不确定那里发生了什么。直接用Organization POJO 试试。从中删除 User 并重新保存 Organization

Organization o =organizationRepository.findAll().iterator().next();
o.getUsers().remove(0);
organizationRepository.save(o);

编辑:也许您的设置中有一些手动 SQL 插入在您开始测试之前失败了。

【讨论】:

  • 这个解决方案很好,但是当你再次添加组织时,它会在表格末尾添加组织,这会破坏顺序。这种情况下该怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 2012-12-05
  • 2015-06-30
相关资源
最近更新 更多