Hibernate多对多映射会删除子实体

时间:2018-07-03 08:22:36

标签: hibernate many-to-many

我正在尝试与休眠模式建立多对多关系,但它并没有达到我的预期。

这是我的实体。

LetterCreditAgreement:

@Canonical
@CompileStatic
@Entity
@Table(name = "FP_LETTER_OF_CREDIT_AGREEMENT")
class LetterCreditAgreement {
    @Id
    @Column(name = "DOC_ID")
    Long id

    ...

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
        name = "FP_DOCUMENT_CURRENCY_LINK",
        joinColumns = @JoinColumn(name = "DOC_ID"),
        inverseJoinColumns = @JoinColumn(name = "CURRENCY_ID"))
    List<Currency> otherCurrency

    ...
}

货币(这是一个字典,在数据库中表示为视图)

@Entity
@Table(name = "V_CURRENCY")
@Canonical
@CompileStatic
@EqualsAndHashCode(callSuper = true)
class Currency extends SuperEntity {
    @Column(name = "name")
    String name

    @Column(name = "short_name")
    String shortName

    @Column(name = "ident")
    String ident

    @Column(name = "code")
    String code

    @ManyToOne
    @JoinColumn(name = "type_id")
    MeasureUnitType type
}

链接实体:

@Entity
@Table(name = "FP_DOCUMENT_CURRENCY_LINK")
@Canonical
@CompileStatic
class DocumentCurrencyLink {

   @EmbeddedId
   DocumentCurrencyPK pk

   @Embeddable
   @Canonical
   @CompileStatic
   static class DocumentCurrencyPK implements Serializable {
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "doc_id")
       Document document

       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "currency_id")
       Currency currency
   }
}

保存或更新主要实体的代码:

LetterCreditAgreement detached = mapper.toEntity(form.data)
LetterCreditAgreement loc = repository.findOne(locId)

...

if (detached.otherCurrency != null) {
        entityUtil.mergeLists(loc.otherCurrency, detached.otherCurrency)
}

...

loc = repository.save(detached)

我期望休眠状态从FP_DOCUMENT_CURRENCY_LINK表中删除关系,但它也试图删除不再位于otherCurrency列表中的Currency:

Hibernate: delete from table.fp_document_currency_link where doc_id=?
Hibernate: insert into table.fp_document_currency_link (doc_id, currency_id) values (?, ?)
Hibernate: insert into table.fp_document_currency_link (doc_id, currency_id) values (?, ?)
Hibernate: insert into table.fp_document_currency_link (doc_id, currency_id) values (?, ?)
Hibernate: insert into table.fp_document_currency_link (doc_id, currency_id) values (?, ?)

可以,但是接下来:

Hibernate: delete from table.v_currency where id=?

我不希望那样发生。我应该从休眠中期待这种正常的行为吗?我不想从数据库中删除货币,因为这是一本字典,我只想在otherCurrency列表更改时删除关系。我该如何实现?

谢谢。

1 个答案:

答案 0 :(得分:0)

您应在List<Currency> otherCurrency中将LetterCreditAgreement的级联类型定义为{CascadeType.PERSIST,CascadeType.MERGE}。这明确地告诉Hibernate仅持久化和合并从此类保存的更改。 进一步尝试避免使用列表,而是使用Set。 Vlad Mihalcea也有一篇不错的Blog-Article:https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/,其中有更详细的内容。

我可以建议您定期阅读他的博客。