java - Spring Data Jpa OneToMany 同时保存子实体和父实体?

标签 java spring spring-boot set spring-data

这是我的父实体。 注意:为了简洁起见,删除了 getter、setter、lombok 注释。

@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>然后保存故事并将此保存的板设置为引用。但这需要两次存储库调用,并且从代码角度来看,它看起来不太好。

此外,我遇到麻烦的原因是因为在运行此代码之前,我的数据库是空的。也就是说,这是我们第一次进入的新记录。所以Board table还没有行。

那么有没有办法一次完成这个任务呢?对于 stackoverflow 上的大多数其他问题,板实体已经从数据库中获取,然后他们将子实体添加到其中并将其保存到数据库中。但对我来说,数据库是完全新鲜的,我想同时添加第一个新的父实体及其相应的子实体,至少在代码方面,即使 hibernate 进行多个数据库调用也是如此。

最佳答案

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

@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将被删除)。

关于java - Spring Data Jpa OneToMany 同时保存子实体和父实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60024214/

相关文章:

java - 如何根据另一个主题的响应从 Kafka 主题读取消息

java - 如何在 Eclipse 中使用 DonutProgress 库

java - Eclipse 插件无法与 GlassFish 服务器通信,请检查防病毒软件是否阻止或监控此端口

java - 如何在现有背景图像上添加侧边菜单(导航菜单)

java - 用于字符串列表的 Initbinder

java - 如何使用 Spring Boot 自动格式化列表 <object> 中的所有 bigdecimal 字段

java - Spring boot - 如何获取 WARN 的框架日志记录和 DEBUG 的应用程序日志记录

java - 遍历泛型集合

spring - 带有 thymeleaf 转义字符的内联 javascript

java - 如何使用 spring mvc + jackson 将嵌套的 json 对象发送到服务器