Hibernate:OneToMany通过级联保存孩子

Ste*_*ood 19 hibernate cascade one-to-many hibernate-annotations

在Parent类中有一个列表List.保存父级时,已添加或更改的子级应由休眠保存/更新.

我已经找到了很多这方面的解释,但是,我只是没有得到它的工作.

Parent.class尝试A.

@Entity
public class Parent {
// id and other attributes
@OneToMany(mappedBy = "parent")
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.ALL)
protected List<child> children;
Run Code Online (Sandbox Code Playgroud)

Parent.class尝试B

@Entity
public class Parent {
// id and other attributes
  @OneToMany(mappedBy = "parent", cascade = { javax.persistence.CascadeType.ALL },
 orphanRemoval = true)
 @org.hibernate.annotations.Cascade({ 
 org.hibernate.annotations.CascadeType.PERSIST,
 org.hibernate.annotations.CascadeType.MERGE,
 org.hibernate.annotations.CascadeType.REFRESH,
 org.hibernate.annotations.CascadeType.SAVE_UPDATE,
 org.hibernate.annotations.CascadeType.REPLICATE,
 org.hibernate.annotations.CascadeType.LOCK,
 org.hibernate.annotations.CascadeType.DETACH })
protected List<child> children;
Run Code Online (Sandbox Code Playgroud)

将子项添加到新父项.之后两者都被保存了

sessionFactory.getCurrentSession().saveOrUpdate(parent);
Run Code Online (Sandbox Code Playgroud)

但是,当刷新时,我收到以下错误:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: de.pockettaxi.backend.model.ride.RideSingle
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:456)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:265)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:275)
at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:295)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3378)
at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:520)
at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:230)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
Run Code Online (Sandbox Code Playgroud)

有人看到我的错误吗?

非常感谢!!

Mar*_*kus 14

我想如果你回答第一条评论中的问题,我们将会遇到这种情况:

  • 你有一个已经坚持的父母
  • 你有新的子对象,还没有持久化
  • 您将子项添加到父项并执行saveOrUpdate

在这种情况下,hibernate只是将保存或更新级联到子级,但它们无法保存或更新,因为它们尚未持久化.现在Hibernate简单地说"我无法更新非持久性实体"

用一句话来说:Hibernate只会将它发布到级联中.在这种情况下,您发出一个"SAVE_UPDATE",然后将其级联到子级.我猜你希望Hibernate能够变得聪明,并且转而坚持为这里的孩子们服务.但这不是Hibernate在这里工作的方式,我之前也遇到过类似的情况.有点混乱,但如果你曾经得到级联的工作方式,你会看到这种情况.


Jos*_*a H 13

您的Parent.class尝试A似乎已经正确.但是为了在保存父级时级联子级,必须将级联放在所有者端(在一对多中,它是具有外键的实体).

试试这个

@Entity
public class Parent {
    @OneToMany(mappedBy = "parent")
    protected List<Child> children;
}
Run Code Online (Sandbox Code Playgroud)

在你的Child.class中

@Entity
public class Child {
    @ManyToOne
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
    @JoinColumn(name="PARENT_ID")
    protected Parent parent;
}
Run Code Online (Sandbox Code Playgroud)

  • 那行得通吗?对我来说,当“Parent”还没有坚持时 - 它不起作用!因此,真正的解决方案看起来是:在事务中 - 保存父级,使用链接父级保存子级 (2认同)

Ila*_*anh 6

我需要一种方法来插入一个具有新的连接(子)实体的实体.一种方法是通过分离动作(例如,首先保存已连接的实体,然后保存主实体).但是,Hibernate支持使用新的连接实体插入新实体.请参阅一个示例:如何通过级联插入OneToMany子项


Ari*_*aru 5

尝试这个:

@Entity
@Table(name = "TABLE_PARENT")
public class Parent{
    @OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
    private List<Child> children;
}

@Entity
@Table(name = "TABLE_CHILD")
public class Child{
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="PARENT_ID")
    private Parent parent;
}
Run Code Online (Sandbox Code Playgroud)

用法

public void save(){
  Parent parent = new Parent();
  List<Child> children = new ArrayList<>();
  Child child = new Child();
  child.setParent(parent);
  children.add(child);
  parent.setChildren(children);

  parentRepository.save(parent);
}
Run Code Online (Sandbox Code Playgroud)

注意:不要忘记在子对象上设置父对象,否则您将获得TABLE_CHILD.PARENT_ID null / empty