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

时间:2014-02-17 22:51:02

标签: java hibernate jpa 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 ...

第二节课:

@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 ...

现在我将一些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);

我仍然有例外。这是来自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$1.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$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.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

我不知道出了什么问题,尝试了很多我认为应该解决这个问题的东西,但它仍然不起作用,我不知道我做错了什么。将不胜感激,提前感谢! :)

编辑:Id是由@Id注释产生的。

2 个答案:

答案 0 :(得分:4)

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

 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);

另外

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

应该是

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

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

答案 1 :(得分:0)

在我的情况下,更新了@OneToMany集合,删除了一些项目,并添加了新项目。尽管在集合中指定了orphanremoval = true,但hiberhate实际上并没有从数据库中删除条目。 尝试删除拥有实体时抛出异常。

修复是在更新操作期间明确删除数据库中的项目。