简体   繁体   English

如何在单向@ManyToOne 关系中保持 Parent from Child?

[英]How to persist Parent from Child in unidirectional @ManyToOne relation?

I have a case where in my Entity I have 2 unidirectional @ManyToOne relations like this:我有一个案例,在我的实体中我有 2 个单向的 @ManyToOne 关系,如下所示:

@Entity
public class A {

@Id
private Long apiId;

//other fields

@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "classBid", foreignKey = @ForeignKey(name = "FK_classA_classB"))
private B b;

@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "classCid", foreignKey = @ForeignKey(name = "FK_classA_classC"))
private C C;

//equals and hashcode
}

This class represents main domain object which comes from outside (by external api).这个 class 代表来自外部(通过外部 api)的主域 object。 Both B and C parents are equally important. B和C父母同等重要。

Now I want to save incoming data:现在我想保存传入的数据:

    @Override
    @Transactional
    public void updateAllInformation() {
        Set<AllInformationDTO> allInformationDTOS = apiService.getAllInformation();

        Set<A> aClassToSaveOrUpdate = new HashSet<>();
        for (AllInformationDTO allInformationDTO : allInformationDTOS) {

            BDTO bDTO = allInformationDTO.b();
            CDTO cDTO = allInformationDTO.c();
            ADTO aDTO = allInformationDTO.a();

            B b = //mapping from dto
            C c = //mapping from dto
            A a = //mapping from dto

            a.setB(b);
            a.setC(c);

            aClassToSaveOrUpdate.add(a);
        }

        aClassRepository.saveAll(aClassToSaveOrUpdate);
    }

But there is a problem when same Parent is in incoming data: DataIntegrityViolationException exception: A different object with the same identifier value was already associated with the session: B#78但是当传入数据中有相同的 Parent 时会出现问题: DataIntegrityViolationException exception: A different object with the same identifier value was already associated with the session: B#78

How to cascade persist parent entities from child side of @ManyToOne relation?如何从@ManyToOne 关系的子端级联持久父实体? Should I change it to bidirectional and persist child from parent?我应该将其更改为双向并坚持父母的孩子吗? But which one (B or C) should I choose to persist from if they are equally important?但是,如果它们同样重要,我应该选择坚持哪一个(B 或 C)?

I didn't want to make it @OneToMany based on this quote from Vlad's blog:我不想根据 Vlad 博客中的这段引述将其设为@OneToMany: 在此处输入图像描述

I don't understand your issue exactly, or more, I don't understand why you think a OneToMany is the solution.我不完全理解您的问题,或者更多,我不明白为什么您认为 OneToMany 是解决方案。 Your session has duplicate java instances for the same row data without having the OneToMany - persist cascading will not help you or change that.您的 session 具有相同行数据的重复 java 实例,但没有 OneToMany - 持续级联不会帮助您或改变它。 If you have multiple As referencing the same b1 row, they need to use the same b1 instance as well.如果您有多个 As 引用相同的 b1 行,它们也需要使用相同的 b1 实例。 The allInformationDTO.b(); allInformationDTO.b(); is returning an instance that represents a row in the B table, say b1, and creating a new b1' instance likely every time it is called.正在返回一个代表 B 表中的行的实例,比如 b1,并可能在每次调用时创建一个新的 b1' 实例。

The solution depends on what you need to do with the Bs and Cs in this set of allInformationDTO.解决方案取决于您需要对这组 allInformationDTO 中的 B 和 C 执行什么操作。 If you care about changes to the B and C data, something like:如果您关心 B 和 C 数据的更改,例如:

    for (AllInformationDTO allInformationDTO : allInformationDTOS) {

        BDTO bDTO = allInformationDTO.b();
        CDTO cDTO = allInformationDTO.c();
        ADTO aDTO = allInformationDTO.a();

        B b = bClassRepository.save(convert(bDTO));//mapping from dto
        C c = cClassRepository.save(convert(cDTO));//mapping from dto
        A a = convert(aDTO));//mapping from dto

        a.setB(b);
        a.setC(c);

        aClassRepository.save(a);
    }

Note though that every redefinition of B and C in your allInformationDTOS will overwrite what was previously there.请注意,在您的 allInformationDTOS 中每次重新定义 B 和 C 都会覆盖之前存在的内容。

Your provider should be able to batch up these save requests and issue them only when needed (when the transaction commits), but it depends on your configuration.您的提供商应该能够批量处理这些保存请求并仅在需要时(事务提交时)发出它们,但这取决于您的配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM