Java Hibernate OneToMany 完整性约束违规:外键没有父级

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21840890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:00:59  来源:igfitidea点击:

Hibernate OneToMany integrity constraint violation: foreign key no parent

javahibernatejpahsqldb

提问by user2759804

I'm trying to write simple project for school, but I have a problem which can't solve. I searched stack for solution, but nothing really works. So the problem:

我正在尝试为学校编写简单的项目,但我有一个无法解决的问题。我在堆栈中搜索解决方案,但没有任何效果。所以问题是:

I have two entity classes created with Hibernate (my db is HSQLDB):

我有两个用 Hibernate 创建的实体类(我的数据库是 HSQLDB):

@Entity
@Table(name = "Zwierzak")
@NamedQueries({ @NamedQuery(name = "delZwierzak", query = "Delete from Zwierzak z where z.zwierzakId = :zid"),
                @NamedQuery(name = "delAll", query = "Delete from Zwierzak"),
                @NamedQuery(name = "getAll", query = "from Zwierzak"),
                @NamedQuery(name = "getByGatunek", query = "Select z from Zwierzak z where z.gatunek = :g")})

public class Zwierzak {

//Some fields here ...

@OneToMany(fetch = FetchType.EAGER, mappedBy = "chorobaId", cascade = {javax.persistence.CascadeType.ALL}, orphanRemoval = true)
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private Set<Choroba> choroby = new HashSet<Choroba>(0);

//Some methods here ...

And second class:

第二类:

@Entity
@Table(name="Choroba")
public class Choroba {

    //Some fields here ...

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="zwierzakId")
    @OnDelete(action = org.hibernate.annotations.OnDeleteAction.CASCADE)
    Zwierzak zwierzak;

    //Some methods here ...

Now I'm adding some Zwierzak entities to database, and try to add Choroba like that:

现在我将一些 Zwierzak 实体添加到数据库中,并尝试像这样添加 Choroba:

Session session = sessionFactory.getCurrentSession();
    session.beginTransaction();

            //Creating and saving Zwierzak (parent) first
    Zwierzak z = new Zwierzak();
    session.save(z);

            //Creating choroba
    Choroba ch = new Choroba();
            //Setting parent in child class
    ch.setZwierzak(z);
            //Adding child in parent class
    z.getChoroby().add(ch);
            //Saving child
    session.save(ch);

And I'm still getting exceptions. Here is stack trace from log:

而且我仍然遇到异常。这是来自日志的堆栈跟踪:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.673 sec <<< FAILURE!
addZwierzakTest(pl.ug.edu.pl.services.ZwierzakServiceTest)  Time elapsed: 0.249 sec  <<< ERROR!
org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:136)
    at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:96)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:58)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2975)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3487)
    at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377)
    at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:214)
    at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:194)
    at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:178)
    at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:321)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:286)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:192)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:206)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:191)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:764)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:756)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:752)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
    at com.sun.proxy.$Proxy17.save(Unknown Source)
    at pl.ug.edu.pl.services.ZwierzakService.dodajChorobe(ZwierzakService.java:50)
    at pl.ug.edu.pl.services.ZwierzakServiceTest.addZwierzakTest(ZwierzakServiceTest.java:45)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access
 Zwierzak z = new Zwierzak();
    session.save(z);

   !!!Consider a flush here !!!
   session.flush();

            //Creating choroba
    Choroba ch = new Choroba();
            //Setting parent in child class
    ch.setZwierzak(z);
            //Adding child in parent class
    z.getChoroby().add(ch);
            //Saving child
    session.save(ch);
0(ParentRunner.java:50) at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:292) at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: foreign key no parent; FK_Q70JGX265MYFNVPD1K5M8ONUD table: CHOROBA at org.hsqldb.jdbc.Util.sqlException(Unknown Source) at org.hsqldb.jdbc.Util.sqlException(Unknown Source) at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source) at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133) ... 58 more

I have no idea what is wrong, tried many things which I found that supposed to solve this problem, but still it doesn't work, I don't know where I do something wrong. Will be grateful for little help, thanks in advance! :)

我不知道出了什么问题,尝试了很多我发现应该解决此问题的方法,但仍然不起作用,我不知道我哪里做错了。将不胜感激的小帮助,提前致谢!:)

EDIT: Id's are generated by @Id annotation of course.

编辑:当然,Id 是由 @Id 注释生成的。

采纳答案by Koitoer

I think the problem is the save operation does not create the id until the commit time, so when you are trying to make the second save id is not present, consider flush before the second save.

我认为问题是保存操作直到提交时间才创建 id,因此当您尝试使第二个保存 id 不存在时,请考虑在第二次保存之前刷新。

@OneToMany(fetch = FetchType.EAGER, mappedBy = "chorobaId", 

Also

@OneToMany(fetch = FetchType.EAGER, mappedBy = "zwierzak",

It should be

它应该是

##代码##

Mapped by refer to the field of the type that will contain the @ManyToOne, not directly the id. It should fix the issue.

映射通过引用将包含@ManyToOne 的类型的字段,而不是直接的 id。它应该解决这个问题。

回答by allap

In my case the @OneToMany collection was updated, some items were removed, and new added. Even though orphanremoval=true was specified on the collection, hiberhate did not actually removed the entries from the database. The exception was thrown at the attempt to delete the owning entity.

就我而言,@OneToMany 集合已更新,一些项目被删除,并添加了新项目。即使在集合上指定了 orphanremoval=true,hiberhate 并没有真正从数据库中删除条目。尝试删除拥有实体时抛出异常。

The fix was to explicitely delete the items from the DB during the update operation.

修复是在更新操作期间显式地从数据库中删除项目。