hibernate - 如何使用已分离的子级

时间:2015-08-21 00:48:45

标签: hibernate jpa orm

我从UI发送一个对象。将使用对现有子项的引用来创建此对象。

这是这种关系的简单说明。

class ParentEntity {
    @Id
    Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private ChildEntity child;
}

class ChildEntity {
    @Id
    Long id;
}



ChildEntity child = new ChildEntity();
child.setId(1);
//parentEntity is created based on data sent from UI
parentEntity.setChild(child);

当我保存这个对象时,Hibernate给了我" org.hibernate.TransientPropertyValueException:object引用未保存的瞬态实例"。

我不必拯救孩子,因为我根本不会改变孩子。只需要将孩子的id保存在父母的表格中。

我尝试过使用少量CascadeType,但都没有。

2 个答案:

答案 0 :(得分:7)

只需为孩子使用代理:

parentEntity.setChild(entityManager.getReference(ChildEntity.class, childId));

这里的要点是使用EntityManager.getReference

  

获取一个实例,其状态可能会被懒散地取出。

Hibernate将创建仅包含id的代理,而无需转到数据库。

答案 1 :(得分:2)

您必须决定如何使用ParentEntity持久保存ChildEntity。

  1. 如果你总是想只用id来坚持孩子那么你可以这样做,如果孩子无效,FK会阻止你。

    class ParentEntity {
        @Id
        Long id;
    
        //To directly load/insert/update childId only
        @Column("child_id")
        private Long childId;
    
       // To load the child entity with parent, Note that insertable/updatable MUST be false
       // as we are inserting/updating = true by default on childId column mapping
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "child_id", insertable = false, updatable = false)
       private ChildEntity child;
    }
    parentEntity.setChildId(childId);
    
  2. 但是如果你想让孩子使用你孩子被映射为对象的现有模型,那么你必须获取孩子并设置它。 的 parentEntity.setChild(childRepository.findOne(childID的)); 要么 您还可以为getOrCreateChild编写一个自定义DAO方法,该方法可以创建一个新子项或查找现有子项并将其返回,以便您可以先保留子项。

  3. 在您使用new关键字创建childEntity的情况下,hibernate将始终将其视为已分离并尝试保留。