如何在不更新现有实体的情况下在新实体与现有实体之间建立关系?

时间:2019-10-21 17:06:23

标签: spring hibernate jpa

我有一个Phone实体和一个PhoneType实体。每个电话都有1个电话类型,每个电话类型可以有许多电话。

我想在使用现有PhoneType时添加新Phone,但是当我创建新Phone时,如何在不从数据库检索PhoneType且不更新现有PhoneType的情况下与现有PhoneType创建关系?< / p>

我尝试仅使用现有ID创建新的PhoneType,然后尝试更新PhoneType记录。我不希望发生此更新。

我也尝试过在Phone的PhoneType字段上更改CascadeType,但是我很难理解这些不同类型的功能。

在“电话”实体中:

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "phone_type_id", referencedColumnName = "id")
    private PhoneType phoneType;

以及PhoneType实体:

@Getter
@Setter
@EqualsAndHashCode
@Entity
@Table(name = "phone_type")
public class PhoneType {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description", length = 175, nullable = false)
    private String description;

    @Column(name = "name", length = 175, nullable = false)
    private String name;
}

最后,创建实体/关系:

    return new Phone()
            .setNumber(phoneNumber)
            .setPhoneType(new PhoneType().setId(defaultPhoneTypeId))
  }

在这种情况下,所发生的正是您所期望的,hibernate尝试使用一堆空字段(其中PhoneType id = defaultPhoneTypeId)更新PhoneType。

使用CascadeType.MERGE,出现以下错误:

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.phoneType -> com.PhoneType

虽然这是预期的,但我不知道如何使用1个新实体和1个现有实体创建关系。

1 个答案:

答案 0 :(得分:0)

您已将级联类型指定为CascadeType.ALL 这会将所有操作级联到映射的实体。 因此,在保存电话时,您将级联保存操作并要求ORM也保存电话类型。

尝试将其完全删除。默认级联类型级联无操作。

    @ManyToOne
    @JoinColumn(name = "phone_type_id", referencedColumnName = "id")
    private PhoneType phoneType;

在创建电话对象时,您可以从数据库中通过ID获取phoneType,然后在保存之前将其设置在电话对象中。