我正在尝试在Hibernate中创建一对一的双向关系。在创建和保存新的子级和父级时,它会尝试使用对父级的空引用来持久保存子级。查看hibernate日志,它会为两个表生成id,然后将子对父对象的引用设置为null并执行查询。我完全糊涂了。
在父母的注释课程中,我有:
@OneToOne
@JoinColumn(name = "CHILD_ID")
@Cascade(CascadeType.ALL)
private Child child;
在孩子的注释课程中,我有:
@OneToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
为了创建/持久化,我有:
Parent p = new Parent();
Child c = new Child();
p.setChild(c);
c.setParent(p);
getHibernateTemplate().save(p);
Hibernate日志,带有粗线的有趣行:
[org.springframework.orm.hibernate3.SessionFactoryUtils] [Opening Hibernate Session] [org.hibernate.impl.SessionImpl] [opened session at timestamp: 13313040615] [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] [saving transient instance] [org.hibernate.jdbc.AbstractBatcher] [opening JDBC connection] [org.hibernate.SQL] [select UNQE_KEY_VALU from where UNQE_KEY_NAME = '' for update] [org.hibernate.jdbc.AbstractBatcher] [closing JDBC connection (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] [org.hibernate.id.MultipleHiLoPerTableGenerator] [new hi value: 1413946] [org.hibernate.event.def.AbstractSaveEventListener] [generated identifier: 14139460, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator] [org.hibernate.event.def.AbstractSaveEventListener] [saving [Parent#14139460]] [org.hibernate.engine.Cascade] [processing cascade ACTION_SAVE_UPDATE for: Parent] [org.hibernate.engine.CascadingAction] [cascading to saveOrUpdate: Child] [org.hibernate.engine.IdentifierValue] [id unsaved-value: 0] [org.hibernate.event.def.AbstractSaveEventListener] [transient instance of: Child] [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] [saving transient instance] [org.hibernate.jdbc.AbstractBatcher] [opening JDBC connection] [org.hibernate.SQL] [select UNQE_KEY_VALU from where UNQE_KEY_NAME = '' for update] [org.hibernate.jdbc.AbstractBatcher] [closing JDBC connection (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] [org.hibernate.id.MultipleHiLoPerTableGenerator] [new hi value: 1413947] [org.hibernate.event.def.AbstractSaveEventListener] [generated identifier: 14139470, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator] [org.hibernate.event.def.AbstractSaveEventListener] [saving [Child#14139470]] [org.hibernate.engine.Cascade] [done processing cascade ACTION_SAVE_UPDATE for: Child] [org.hibernate.engine.Cascade] [processing cascade ACTION_SAVE_UPDATE for: Parent] [org.hibernate.engine.Cascade] [done processing cascade ACTION_SAVE_UPDATE for: Parent] [org.springframework.orm.hibernate3.HibernateTemplate] [Eagerly flushing Hibernate session] [org.hibernate.event.def.AbstractFlushingEventListener] [flushing session] [org.hibernate.event.def.AbstractFlushingEventListener] [processing flush-time cascades] [org.hibernate.engine.Cascade] [processing cascade ACTION_SAVE_UPDATE for: Parent] [org.hibernate.engine.CascadingAction] [cascading to saveOrUpdate: Child] [org.hibernate.event.def.AbstractSaveEventListener] [persistent instance of: Child] [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] [ignoring persistent instance] [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] [object already associated with session: [Child#14139470]] [org.hibernate.engine.Cascade] [done processing cascade ACTION_SAVE_UPDATE for: Parent] [org.hibernate.event.def.AbstractFlushingEventListener] [dirty checking collections] [org.hibernate.event.def.AbstractFlushingEventListener] [Flushing entities and processing referenced collections] [org.hibernate.persister.entity.AbstractEntityPersister] [Child.parent is dirty] [org.hibernate.event.def.DefaultFlushEntityEventListener] [Updating entity: [Child#14139470]] [org.hibernate.event.def.AbstractFlushingEventListener] [Processing unreferenced collections] [org.hibernate.event.def.AbstractFlushingEventListener] [Scheduling collection removes/(re)creates/updates] [org.hibernate.event.def.AbstractFlushingEventListener] [Flushed: 2 insertions, 1 updates, 0 deletions to 2 objects] [org.hibernate.event.def.AbstractFlushingEventListener] [Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections] [org.hibernate.pretty.Printer] [listing entities:] [org.hibernate.pretty.Printer] [Parent{child=Child#14139470, parentId=14139460}] [org.hibernate.pretty.Printer] [Child{parent=Parent#14139460, childId=14139470}] [org.hibernate.event.def.AbstractFlushingEventListener] [executing flush] [org.hibernate.jdbc.ConnectionManager] [registering flush begin] [org.hibernate.persister.entity.AbstractEntityPersister] [Inserting entity: [Child#14139470]] [org.hibernate.jdbc.AbstractBatcher] [about to open PreparedStatement (open PreparedStatements: 0, globally: 0)] [org.hibernate.jdbc.ConnectionManager] [opening JDBC connection] [org.hibernate.SQL] [insert into CHILD_TABLE (PARENT_ID, CHILD_ID) values (?, ?)] [org.hibernate.jdbc.AbstractBatcher] [preparing statement] [org.hibernate.persister.entity.AbstractEntityPersister] [Dehydrating entity: [Child#14139470]] [org.hibernate.type.LongType] [binding null to parameter: 1] [org.hibernate.type.LongType] [binding '14139470' to parameter: 2] [org.hibernate.persister.entity.AbstractEntityPersister] [Inserting entity: [Parent#14139460]] [org.hibernate.jdbc.AbstractBatcher] [Executing batch size: 1] [org.hibernate.jdbc.AbstractBatcher] [about to close PreparedStatement (open PreparedStatements: 1, globally: 1)] [org.hibernate.jdbc.AbstractBatcher] [closing statement] [DEBUG] [org.hibernate.util.JDBCExceptionReporter] [Could not execute JDBC batch update [insert into CHILD_TABLE (PARENT_ID, CHILD_ID) values (?, ?)]] java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("CHILD_TABLE"."PARENT_ID")
在前两行粗体中,父亲知道孩子的身份,反之亦然。但是,在生成子级的sql时,它将父级的id设置为null。发生了什么事?
编辑: 作为参考,我使用以下hibernate jar: org.hibernate作为:冬眠的注解:罐子:3.3.1.GA org.hibernate作为:冬眠:罐子:3.2.6.ga
答案 0 :(得分:6)
我不确切知道你为什么会这样做,但我所知道的是你没有这里的双向一对一关联。
您所拥有的是两个不同的一对一单向关联:父级使用子表的外键知道其子级,并且子级使用父表的外键知道其父级。
顺便说一句,这种做法可能会导致父母A有一个孩子B,而父母C有这样的情况。如果您真正想要的是双向一对一关联,则应删除其中一个外键,并使用另一个来映射关联。假设您将CHILD_ID列保留在父表中,则映射将为:
@OneToOne
@JoinColumn(name = "CHILD_ID")
@Cascade(CascadeType.ALL)
private Child child;
和
@OneToOne(mappedBy = "child")
private Parent parent;
答案 1 :(得分:0)
我修好了,虽然我不确定它为什么会起作用。我将级联从Parent移到了Child并保存了Child而不是Parent。
在父母的注释课程中,我有:
@OneToOne
@JoinColumn(name = "CHILD_ID")
private Child child;
在孩子的注释课程中,我有:
@OneToOne
@JoinColumn(name = "PARENT_ID")
@Cascade(CascadeType.ALL)
private Parent parent;
为了创建/持久化,我有:
Parent p = new Parent();
Child c = new Child();
p.setChild(c);
c.setParent(p);
getHibernateTemplate().save(c);