这是我的父实体。 注意:为了简洁起见,移除了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进行多个数据库调用。
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
。这可能是因为Story
只是一个普通的POJO,并没有被保存。另一方面,如果我保留子实体上的级联(以及您为父实体提供的级联),则会在父实体中看到两行记录。而你所说的更新是什么意思?你是指jpa.show-sql: true
的更新吗? - theprogrammer