SpringData CrudRepository применяет автоматически каскадный тип - PullRequest
0 голосов
/ 10 октября 2018

В моем проекте мне нужно подключиться к существующей базе данных и выполнить логику, которая обновляет две таблицы.

Моя настройка следующая:

@Entity
@Table(name = "DOCUMENTCONTENT")
@Getter
public class DocumentContent {

    @Id
    @Column(name = "ID", insertable = false, updatable = false)
    private Long id;

    @OneToOne
    @JoinColumn(name = "DOCUMENT_ID", insertable = false, updatable = false)
    private Document document;

    @Lob
    @Column(name = "CONTENT")
    @Setter
    private byte[] content;
}

@Entity
@Table(name = "DOCUMENT")
@Getter
public class Document {

    @Id
    @Column(name = "ID", insertable = false, updatable = false)
    private Long id;

    @OneToOne(mappedBy = "document")
    private DocumentContent documentContent;

    @OneToMany(mappedBy = "document", fetch = EAGER)
    private List<Attachment> attachments;
}

@Entity
@Table(name = "ATTACHMENT")
@Getter
public class Attachment {

    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "DOCUMENT_ID", insertable = false, updatable = false)
    private Document document;

    @ManyToOne
    @JoinColumn(name = "CONTRACT_ID",updatable = false, insertable = false)
    private Contract contract;
}

@Entity
@Table(name = "CONTRACT")
@Getter
public class Contract {

    @Id
    @Column(name = "ID", insertable = false, updatable = false)
    private Long id;

    @Column(name = "STATUS")
    @Setter
    private String status;

    @ManyToOne
    @JoinColumn(name = "CUSTOMER_ID", insertable = false, updatable = false)
    private Customer customer;

    @OneToMany(mappedBy = "contract", fetch = EAGER)
    private List<Attachment> attachments;
}

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    private DocumentContentRepository documentContentRepository; // spring data Crud Repository

    @Override
    @Transactional
    public void updateDocumentContent(SomeDto someDto) {
        DocumentContent documentContent = documentContentRepository.findByDocumentId(someDto.getDocumentId());
        documentContent.setContent(someDto.getBytes());
        List<Contract> contracts = documentContent.getDocument().getAttachments()
                .stream().map(Attachment::getContract).collect(toList());
        contracts.forEach(contract -> contract.setStatus("SIGNED"));
        documentContentRepository.save(documentContent);
    }
}

Когда я запускаю службу из вышеуказанного сервиса, я могуобратите внимание на эти SQL в выводе консоли:

Hibernate: обновить содержимое набора содержимого документа =?где id =?
Hibernate: обновить статус набора контрактов =?где id =?

Я понимаю, почему jpa выполнила первое обновление в таблице documentcontent, но я не знаю, почему оно также обновилось в таблице контрактов.Как видите, я не использовал CascadeType.MERGE ни в одной сущности.

Можете ли вы объяснить мне, почему это второе обновление было выполнено без объявления каскадного типа?

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Я сомневаюсь, что это вообще имеет какое-либо отношение к Cascade, но с механизмом транзакционной записи ( больше информации ).Я полагаю, что вы также можете избавиться от строки

documentContentRepository.save(documentContent);

, так как вы изменяете два управляемых объекта.В конце транзакции в спящем режиме сохраняются все объекты, помеченные как измененные механизмом грязной проверки ( дополнительная информация ).

0 голосов
/ 10 октября 2018

Вы получаете второй запрос по причине, вы изменяете свойство Status Контракта.JPA обнаруживает это изменение и пытается обновить сущность.

Это поведение по умолчанию CaseCadeType @ OneToMany

Для дальнейшего чтения перейдите по этой ссылке .

...