[英]Best way to save and update entity Parent and child using spring data jpa
我面臨一些關於 spring data jpa 的行為,我需要了解。
考慮一下:
文檔
@Getter
@Setter
@ToString
@Entity
@Table(name = "document")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Document{
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String title;
private String description;
@OneToMany(cascade = ALL, fetch = FetchType.LAZY, mappedBy = "document")
@ToString.Exclude
private Set<Template> templates = new HashSet<>();
public void addTemplates(Template template) {
templates.add(template);
template.setDocument(this);
}
}
模板
@Getter
@Setter
@ToString
@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Template{
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String name;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "document")
private Document document;
}
服務
@RequiredArgsConstructor
@Service
@Transactional
@Slf4j
public class DocumentService {
private final DocumentRepository documentRepository;
private final TemplateRepository templateRepository;
public void createTemplate() {
Set<Template> template = new HashSet<>();
template.add("template1");
template.add("template2");
templateRepository.saveAll(template);
}
public void createMovie(DocumentDTO documentRequest) {
Set<Template> templates = toTemplate(documentRequest.getTemplates());
Document document = Document.builder()
.title(documentRequest.getTitle())
.description(documentRequest.getDescription())
.template(new HashSet<>())
.build();
templates.forEach(document::addTemplates);
documentRepository.save(document);
}
private Set<Template> toTemplate(TemplateDTO templatesDTO) {
return documentRequest.getTemplates().stream().map(templateDTO ->
Template.builder()
.id(templateDTO.getId())
.firstName(templateDTO.getFirstName())
.lastName(templateDTO.getLastName())
.build()
).collect(Collectors.toSet());
}
}
首先=>我創建了模板,例如當我創建一個新文檔時
{
"title": "tre",
"description": "opppp",
"template": [
{
"id": 1,
"name": "template1"
},
{
"id": 2,
"name": "template2",
}
]
}
使用此數據配置,我將這個錯誤detached entity passed to persist
。 因此,為了解決此錯誤,我將 CASCADE Merge 改為 ALL 放在 Parent 上,如下所示
@OneToMany(cascade = MERGE, fetch = FetchType.LAZY, mappedBy = "document")
@ToString.Exclude
private Set<Template> template= new HashSet<>();
我再次嘗試保存文檔。 文檔沒問題,但模板中沒有任何反應。 這是控制台中的 sql
Hibernate: insert into document (id, description, title) values (null, ?, ?)
為什么孩子沒有更新文件ID?? 因為 spring jpa 調用的實體管理器持久化而不是 merge 。
有沒有辦法保存而不必顯式調用合並??? 因為如果我調用合並,我會在更新之前得到一堆選擇子項。 那么我該如何避免這個問題。
幾個觀察,當存在雙向映射時,子實體處的 JoinColumn 注釋是不必要的。
始終依賴 persist、persistAndFlush 或 persistAllAndFlush 而不是保存,因為它僅在存在新實體時才會持久,否則它將嘗試合並。 在這里您可以看到生成的 SQL 語句僅在父實體上而不是在子實體上。
參考, https://vladmihalcea.com/best-spring-data-jparepository/
我認為是幫助了一些人。 請關注弗拉德博客。 他解釋了為什么我們需要添加版本來避免多重選擇。 https://vladmihalcea.com/jpa-persist-and-merge/
所以在我的情況下,我在我的子實體中添加了這樣的想法:
@Version
private Long version;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.