Hibernate: OneToMany сохранить детей каскадом

в родительском классе есть список. Когда родитель сохранен, дети, которые были добавлены или изменены, должны быть сохранены / обновлены hibernate.

Я нашел много объяснений по этому поводу, однако, я просто не могу заставить его работать.

родитель.класс попробуй

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

родитель.класс попробуйте 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;

дети добавляются к новому родителю. После этого оба спасаются

sessionFactory.getCurrentSession().saveOrUpdate(parent);

когда топить, однако, я получаю следующая ошибка:

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)

кто-нибудь видит мою ошибку?

Спасибо большое!!

4 ответов


Я думаю, если вы ответите на вопрос из первого комментария, мы придем к такой ситуации:

  • у вас уже есть сохраненный родитель
  • у вас есть новые дочерние объекты, которые еще не унимался
  • вы добавляете детей к родителю и делаете saveOrUpdate

в этом случае hibernate просто каскадирует сохранение или обновление для детей, но они не могут быть сохранены или обновлены, поскольку они еще не были постоянными. А теперь спи. говорит просто:"я не могу обновить непостоянную сущность"

в одном предложении: Hibernate только каскады, что он выдается каскаду. В этом случае вы выдаете "SAVE_UPDATE", который затем распространяется дальше детей. Я думаю, вы ожидали, что Hibernate будет умным и переключится на сохранение для детей здесь. Но здесь работает не так, как Hibernate, я тоже сталкивался с подобными ситуациями. Немного запутанно, но если вы когда-то получили, как работает каскадирование, вы увидите подобные случаи.


Ваш Родитель.класс попробую, кажется, уже правильно. Но чтобы каскадировать ребенка при сохранении родителя, вы должны поместить каскад на стороне владельца (в один ко многим, это сущность, которая имеет внешний ключ).

попробуй такое

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

и в вашем ребенке.класс!--3-->

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

Мне нужен был способ вставить сущность с новой объединенной (дочерней) сущностью вместе. Один из способов сделать это-разделить действия (например, сначала сохранить объединенный объект, а затем сохранить основной объект). Однако Hibernate поддерживает вставку нового объекта с новым присоединенным объектом. См. один пример как:Как вставить OneToMany детей каскадом


попробуйте это:

@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;
}

использование

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

Примечание: Не забудьте установить родителя на дочерний объект или вы получите TABLE_CHILD.ИД_РОДИТЕЛЬСКОГО_ОБЪЕКТА значение null/пустой