仅获取@ManyToOne 关系但不保留父实体
only fetch @ManyToOne releationship but dont persist Parent Entity
我有以下实体:
@Entity
public class Parent {
@Id
@Column(name = "ID", nullable = false)
private Long id;
}
@Entity
public class Child {
@Id
@Column(name = "ID", nullable = false)
private Long id;
private Parent parent;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
public Parent getParent() {
return parent;
}
}
现在,当我保存子项时,我想将父项的 ID 保存到列 "PARENT_ID"。
但是我不想在保存子项时保存或更新父项。
因此,我已将 updatable = false, insertable = false
添加到 @JoinColumn。
问题是,这样我得到 "org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing".
所以 Hibernate 告诉我先保存 Parent,再保存 Child。好吧,Parent 已经保存了,但是 Hibernate 不知道,因为它是一个新的 Transaction 而我不想要
再次保存 Parent(这就是 updatable = false, insertable = false
的重点)。我也不想再次获取 Parent(不需要额外的 select,我只需要 ID(我已经拥有)而不是整个对象)
我已经尝试用@Transient 注释 getParent 以防止 Parent 的持久化,这很有效,但是当获取 Child 时,Parent 却没有。
(我用手动设置的另一个 属性 保存了 ID)
有什么方法可以实现我想要的吗?
(获取子项时获取父项,保存子项时保存父项ID,但不保存或更新父项)
问题似乎是您正在创建一个新的父级,尽管您想要的只是将一个新的子级附加到现有的父级。不要那样做。由于父级已经存在,从 EntityManager 获取它:
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
public Parent getParent() {
return parent;
}
并且,要保存一个具有现有父 ID 的新子:
Parent existingParent = entityManager.getReference(Parent.class, parentId);
Child child = new Child();
child.setParent(existingParent);
entityManager.persist(child);
正如对 JB Nizet Answer 的评论,我不得不使用不同的解决方案,但我认为你应该使用他的,如果可以的话。
我的解决方案如下所示:
- 从 getParent() 中删除 @ManyToOne 和 @JoinColumn 并使用 @Transient
对其进行注释
- 添加另一个 属性 (Long parentId)
- 使用@Column("PARENT_ID") 注释 parentId
- 当从数据库加载子项时,我获取 parentId 并加载父项并通过其 Setter 方法将其添加到子项
我有以下实体:
@Entity
public class Parent {
@Id
@Column(name = "ID", nullable = false)
private Long id;
}
@Entity
public class Child {
@Id
@Column(name = "ID", nullable = false)
private Long id;
private Parent parent;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID", referencedColumnName = "ID", updatable = false, insertable = false)
public Parent getParent() {
return parent;
}
}
现在,当我保存子项时,我想将父项的 ID 保存到列 "PARENT_ID"。
但是我不想在保存子项时保存或更新父项。
因此,我已将 updatable = false, insertable = false
添加到 @JoinColumn。
问题是,这样我得到 "org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing".
所以 Hibernate 告诉我先保存 Parent,再保存 Child。好吧,Parent 已经保存了,但是 Hibernate 不知道,因为它是一个新的 Transaction 而我不想要
再次保存 Parent(这就是 updatable = false, insertable = false
的重点)。我也不想再次获取 Parent(不需要额外的 select,我只需要 ID(我已经拥有)而不是整个对象)
我已经尝试用@Transient 注释 getParent 以防止 Parent 的持久化,这很有效,但是当获取 Child 时,Parent 却没有。
(我用手动设置的另一个 属性 保存了 ID)
有什么方法可以实现我想要的吗?
(获取子项时获取父项,保存子项时保存父项ID,但不保存或更新父项)
问题似乎是您正在创建一个新的父级,尽管您想要的只是将一个新的子级附加到现有的父级。不要那样做。由于父级已经存在,从 EntityManager 获取它:
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
public Parent getParent() {
return parent;
}
并且,要保存一个具有现有父 ID 的新子:
Parent existingParent = entityManager.getReference(Parent.class, parentId);
Child child = new Child();
child.setParent(existingParent);
entityManager.persist(child);
正如对 JB Nizet Answer 的评论,我不得不使用不同的解决方案,但我认为你应该使用他的,如果可以的话。
我的解决方案如下所示:
- 从 getParent() 中删除 @ManyToOne 和 @JoinColumn 并使用 @Transient
对其进行注释
- 添加另一个 属性 (Long parentId)
- 使用@Column("PARENT_ID") 注释 parentId
- 当从数据库加载子项时,我获取 parentId 并加载父项并通过其 Setter 方法将其添加到子项