Hibernate recursive bidirectional one-to-many association
I have an entity that can have 0 or many children of the same entity. Also, an entity can have 0 or one parent of the same entity. The table structure is
CREATE TABLE `group` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`parent_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_group_parent1` (`parent_id`),
CONSTRAINT `fk_group_parent1` FOREIGN KEY (`parent_id`) REFERENCES `group` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
)
I have this annotations in Group class
@Entity
@Table(name="group")
public class Group implements Serializable {
private static final long serialVersionUID = 2831577205800506169L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "description")
private String description;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "parent_id", nullable = true)
private Group parentGroup = null;
@OneToMany(fetch=FetchType.LAZY, mappedBy = "pa开发者_开发问答rentGroup",
cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private Set<Group> childGroups = new HashSet<Group>();
... getters/setters
Source : From Java persistence with hibernate
In my main code i initialyze a group with null childGroups
// create realm user group
Group parent = new Group();
parent.setName("RealmUserGroup");
Group child = new Group();
// add null child to parent
child.setParentGroup(parent);
parent.addChildGroup(child);
when I would to save with groupManager I get this error
2011-06-08 11:20:11,098 DEBUG [AbstractSaveEventListener.java:514] : transient instance of: com.joonts.domain.Group
2011-06-08 11:20:11,098 DEBUG [DefaultMergeEventListener.java:275] : merging transient instance
2011-06-08 11:20:11,099 DEBUG [DefaultMergeEventListener.java:288] : merging transient instance
2011-06-08 11:20:11,099 DEBUG [Cascade.java:116] : processing cascade ACTION_MERGE for: com.joonts.domain.Group
2011-06-08 11:20:11,100 DEBUG [Cascade.java:151] : done processing cascade ACTION_MERGE for: com.joonts.domain.Group
2011-06-08 11:20:11,100 DEBUG [AbstractSaveEventListener.java:153] : saving [com.joonts.domain.Group#<null>]
2011-06-08 11:20:11,100 DEBUG [AbstractSaveEventListener.java:244] : executing insertions
2011-06-08 11:20:11,103 DEBUG [WrapVisitor.java:87] : Wrapped collection in role: com.joonts.domain.Group.childGroups
2011-06-08 11:20:11,103 DEBUG [AbstractSaveEventListener.java:297] : executing identity-insert immediately
2011-06-08 11:20:11,104 DEBUG [AbstractEntityPersister.java:2139] : Inserting entity: com.joonts.domain.Group (native id)
2011-06-08 11:20:11,104 DEBUG [AbstractBatcher.java:389] : about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2011-06-08 11:20:11,105 DEBUG [AbstractBatcher.java:424] :
insert
into
group (name
, description, parent_id)
values
(?, ?, ?)
Hibernate:
insert
into
group (name
, description, parent_id)
values
(?, ?, ?)
2011-06-08 11:20:11,105 DEBUG [AbstractBatcher.java:507] : preparing statement
2011-06-08 11:20:11,116 DEBUG [AbstractEntityPersister.java:1987] : Dehydrating entity: [com.joonts.domain.Group#<null>]
2011-06-08 11:20:11,116 DEBUG [NullableType.java:133] : binding 'RealmUserGroup' to parameter: 1
2011-06-08 11:20:11,117 DEBUG [NullableType.java:133] : binding 'Base group' to parameter: 2
2011-06-08 11:20:11,117 DEBUG [NullableType.java:126] : binding null to parameter: 3
2011-06-08 11:20:11,118 DEBUG [AbstractBatcher.java:397] : about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2011-06-08 11:20:11,118 DEBUG [AbstractBatcher.java:556] : closing statement
2011-06-08 11:20:11,120 DEBUG [JDBCExceptionReporter.java:69] : could not insert: [com.joonts.domain.Group] [insert into group (name, description, parent_id) values (?, ?, ?)]
java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group (name, description, parent_id) values ('RealmUserGroup', 'Base group', nul' at line 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2975)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1600)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1695)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3026)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1137)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1368)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1283)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1268)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2153)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2633)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:51)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:315)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:283)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:238)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:85)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:678)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:662)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:666)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:227)
....
2011-06-08 11:20:11,135 WARN [JDBCExceptionReporter.java:77] : SQL Error: 1064, SQLState: 42000
2011-06-08 11:20:11,135 ERROR [JDBCExceptionReporter.java:78] : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group (name, description, parent_id) values ('RealmUserGroup', 'Base group
In web page i get this exception report
java.lang.NullPointerException
com.joonts.dao.impl.BaseJpaDao.save(BaseJpaDao.java:121)
com.joonts.service.impl.GroupManagerImpl.saveGroup(GroupManagerImpl.java:21)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
$Proxy43.saveGroup(Unknown Source)
com.joonts.action.ConfirmSignupAction.confirm(ConfirmSignupAction.java:118)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:441)
It does not make it work and do not know what I'm doing wrong. Thanks for helping, and sorry for the long text.
精彩评论