Spring Data Jpa OneToMany是否同时保存子实体和父实体?

问题描述 投票:0回答:1

这是我的父实体。注意:为简洁起见,删除吸气剂,塞特剂,龙目岛注释。

@Entity
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @OneToMany(mappedBy = "board")
    private Set<Story> stories = new HashSet<>();
}

下面是我的孩子实体

@Entity
public class Story {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "board_id")
    @JsonIgnore
    private Board board;
}

每个Board可以有多个Story,但是每个Story都属于单个Board

现在在我的服务中,我正在这样做:

public void addBoard(BoardDTO boardDto){
    // create a new board object which is just a pojo
    // by copying properties from boardDto
    Board board = ...;

    // create set of stories
    List<String> defaultTitles = Arrays.asList("Todo", "In-Progress", "Testing", "Done");
    Set<Story> stories = defaultTitles.stream().map(title -> Story.builder()
            .title(title)
            // assign a reference, I know this is wrong since board here is not
            // saved yet or fetched from db, hence the question
            .board(board) 
            .build())
            .collect(Collectors.toSet());

    // This saves board perfectly, but in Story db, the foreign key column
    // board_id is null, rightfully so since call to story table was not yet done.
    Board save = boardRepository.save(Board.builder()
            .title(board.getTitle())
            .stories(stories)
            .build());
}

[我可以采取的一种方法是先保存不带Set<Story>的板,然后使用已保存的板设置为参考来保存故事。但是,这将需要两个Repository调用,并且在代码方面看起来不太好。

而且,我遇到麻烦的原因是,在运行此代码之前,我的数据库为空。这是我们第一次输入的新记录。因此Board table尚无行。

所以总有一次可以做到这一点吗?对于其他有关stackoverflow的大多数问题,董事会实体已经从db中获取,并且then正在向其添加子实体并将其保存到db。但是对我来说,数据库是完全新鲜的,并且我想同时添加第一个新的父实体及其对应的子实体,至少在代码方面即使冬眠进行了多次数据库调用也是如此。

java hibernate spring-boot jpa spring-data-jpa
1个回答
0
投票

是的,您只需要级联从父级到子级的更改:

@Entity
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Set<Story> stories = new HashSet<>();
}

现在,只要保存父表(Board),更改将级联到子表。您也可以使用CascadeType.ALL而不是{CascadeType.PERSIST, CascadeType.MERGE}级联任何更改,例如删除(当从父实体的集合中删除子项时,子表中的联接ID将被删除)。

© www.soinside.com 2019 - 2024. All rights reserved.