Hibernate - 一对多关系和orphanRemoval级联 [英] Hibernate - One to many relationship and orphanRemoval cascade

查看:138
本文介绍了Hibernate - 一对多关系和orphanRemoval级联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基本的一对多关系父/子,就像Hibernate参考手册的第21章一样。

级联仅从子级到父级(坚持级联,因为我不想删除父母,如果我删除了一个孩子)。
当我添加一个孩子到家长,我保存孩子,我有一个TransientObjectException ...

  @Entity 
public class Parent实现Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
私人长ID;

@OneToMany(mappedBy =parent,orphanRemoval = true)
private List< Child>孩子的;

公共列表< Child> getChilds(){
返回孩子;
}

public void setChilds(List< Child> childs){
this.childs = childs;

$ b public void addChild(Child child){
if(childs == null)childs = new ArrayList< Child>();
if(childs.add(child))child.setParent(this);
}

public Long getId(){
return id;
}

public void setId(Long id){
this.id = id;



$实际
public class Child实现Serializable {

@Id
@GeneratedValue(strategy = GenerationType .AUTO)
私人长ID;

@ManyToOne(可选=假)
@Cascade({PERSIST,MERGE REFRESH,SAVE_UPDATE,REPLICATE,LOCK,DETACH})
私人父亲;

public Parent getParent(){
return parent;
}

public void setParent(父母){
this.parent = parent;
}

public Long getId(){
return id;
}

public void setId(Long id){
this.id = id;




@Test
public void test(){
Parent parent = new Parent();
Child child = new Child();
parent.addChild(child);
genericDao.saveOrUpdate(child);
}

但是在saveOrUpdate上,我有这个例外:

  org.hibernate.TransientObjectException:对象引用未保存的瞬态实例 - 在冲洗前保存瞬态实例:Child 
at org.hibernate.engine。 ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:244)
at org.hibernate.collection.AbstractPersistentCollection.getOrphans(AbstractPersistentCollection.java:911)
at org.hibernate.collection.PersistentBag.getOrphans(PersistentBag.java: 143)
在org.hibernate.engine.CollectionEntry.getOrphans(CollectionEntry.java:373)
在org.hibernate.engine.Cascade.deleteOrphans(Cascade.java:471)
。在组织.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:455)
在org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
在org.hibernate.engine.Cascade.cascadeAssociation (Cascade.java:338)
在org.hibernate.engine.Cascade.cascadeProperty(Casc ade.java:204)美元,org.hibernate.engine.Cascade.cascade(Cascade.java:161 B $ B)
在org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:354)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate .event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def .DefaultSaveOrUpdateEventListener .onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669 )在org.hibernate.engine.CascadingAction $ 5.cascade
(CascadingAction.java:252)
在org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
。在组织.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
在org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
在org.hibernate.engine.Cascade.cascade (Cascade.java:161)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:451)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java :288)
在org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
在org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedI (org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener)中的
。 Java的:195),美元,org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117 b $ b)
在org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)在org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)

在org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
在org.hibernate作为.impl.SessionImpl.saveOrUpdate(SessionImpl.java:665)

我真的不明白,因为保存孩子应该通过级联保存家长...
任何想法?

更新1

概率lem似乎与orphanRemoval有关,因为如果我在父项上注释它:

  @OneToMany(mappedBy =parent / *,orphanRemoval = true * /)
私人列表< Child>孩子的;

它有效!

它保存了孩子,然后是父母。 >
但是我真的需要通过级联删除孤儿,当我从父母中移除一个孩子时。


更新2

我创建了一个JIRA问题:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-5364


UPDATE 3

这似乎是固定的:-)

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269

解决方案

这是Hibernate中的一个问题,现在已经修复:

http://opensource.atlassian.com/projects/hibernate/browse/HHH -2269


I have a basic one to many relation parent / child like in the chapter 21 of Hibernate references book.
The cascade is only from child to parent (persist cascade only because I don't want to delete the parent if I delete a child).
When I add a child to the parent and I save the child, I have a TransientObjectException...

@Entity
public class Parent implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @OneToMany(mappedBy = "parent", orphanRemoval = true)
  private List<Child> childs;

  public List<Child> getChilds() {
    return childs;
  }

  public void setChilds(List<Child> childs) {
    this.childs = childs;
  }

  public void addChild(Child child) {
    if (childs == null) childs = new ArrayList<Child>();
    if (childs.add(child)) child.setParent(this);
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }
}

@Entity
public class Child implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @ManyToOne(optional = false)
  @Cascade( { PERSIST, MERGE, REFRESH, SAVE_UPDATE, REPLICATE, LOCK, DETACH })
  private Parent parent;

  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }
}


@Test
public void test() {
  Parent parent = new Parent();
  Child child = new Child();
  parent.addChild(child);
  genericDao.saveOrUpdate(child);
}

But on the saveOrUpdate, I have this exception:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Child
  at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:244)
  at org.hibernate.collection.AbstractPersistentCollection.getOrphans(AbstractPersistentCollection.java:911)
  at org.hibernate.collection.PersistentBag.getOrphans(PersistentBag.java:143)
  at org.hibernate.engine.CollectionEntry.getOrphans(CollectionEntry.java:373)
  at org.hibernate.engine.Cascade.deleteOrphans(Cascade.java:471)
  at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:455)
  at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
  at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
  at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
  at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
  at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:476)
  at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:354)
  at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
  at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
  at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
  at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
  at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
  at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
  at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
  at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
  at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:451)
  at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
  at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
  at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
  at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
  at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:677)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:669)
  at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:665)

I really don't understand because saving the Child should save the Parent via the cascade... Any ideas ?

UPDATE 1
The problem seems to be related to "orphanRemoval" because if I comment it on the parent:

@OneToMany(mappedBy = "parent" /*, orphanRemoval = true */)
private List<Child> childs;

It works!
It save the child, then the parent.
But I really need the orphan to be deleted via the cascade when I remove a child from its parent.

UPDATE 2
I've created a JIRA issue:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5364

UPDATE 3
It seems to be fixed :-)
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269

解决方案

It was an issue in Hibernate and it is now fixed:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2269

这篇关于Hibernate - 一对多关系和orphanRemoval级联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆