使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表
Posted
技术标签:
【中文标题】使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表【英文标题】:Using @OneToMany and @ManyToOne annotations is updating one entity table but not the many table 【发布时间】:2020-07-18 15:08:26 【问题描述】:我有一个 Spring RESTful API,它使用 H2 数据库和 JPA 来填充一些表。我正在尝试使用字段@OneToMany
设置一个实体,而另一个实体对象是@ManyToOne
。当我在 Postman 中发出 POST 请求时,我 sout
我的 Quiz quiz
这是请求正文,字段与预期一致。然而,当我在 localhost 上登录数据库时,只有 quiz_table
更新为正确的属性。
当我发出 POST 请求时,我会在控制台中得到这个输出
Hibernate: insert into quiz_table (answer, text, title, id) values (?, ?, ?, ?)
我的 JSON 请求正文是
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": ["2002", "2019"],
"answer": 1
服务器响应是
"id": 67,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 0,
"quiz": null,
"option": "2002"
,
"id": 0,
"quiz": null,
"option": "2019"
]
据我所知,"options"
的值正在传递给List<Option>
这是我的控制器与此端点的映射
@PostMapping(path = "api/quizzes", produces = "application/json")
public Quiz addQuiz(@Valid @RequestBody Quiz quiz)
quizRepository.save(quiz);
return quiz;
Quiz
类
@Component
@Entity(name = "quiz_table")
public class Quiz
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotBlank(message = "Title must not be blank")
private String title;
@NotBlank(message = "Text must not be blank")
private String text;
@Size(min = 2)
// @NotNull
@OneToMany(mappedBy = "quiz")
private List<Option> options;
@JsonIgnore
private int answer;
public Quiz()
public Quiz(String title, String text, List<Option> options, int answer)
this.title = title;
this.text = text;
this.options = options;
this.answer = answer;
Option
类
@Component
@Entity(name = "options_table")
public class Option
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ManyToOne
@JoinColumn
private Quiz quiz;
private String option;
// for Jackson deserielization
public Option()
/*public Option(Quiz quiz, String option)
this.quiz = quiz;
this.option = option;
*/
public Option(String option)
this.option = option;
// getters/setters
编辑:实施建议后的异常 JSON 响应
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win a trophy?",
"options": [
"id": 2,
"quiz":
"id": 1,
"title": "Tottenham Quiz",
"text": "When did Tottenham Hotspur last win
// ... continues for 4000 lines!
【问题讨论】:
您是否尝试添加级联选项?我认为这就是您无法保存子实体的原因。 我完全忽略了这一点。我猜没有默认设置? 【参考方案1】: 使用 JPA/Hibernate,您需要明确管理双向关系 @PostMapping(path = "api/quizzes", produces = "application/json")
public Quiz addQuiz(@Valid @RequestBody Quiz quiz)
quiz.getOptions().forEach(option -> option.setQuiz(quiz));
quizRepository.save(quiz);
return quiz;
另外,你必须告诉hibernate,当它管理Quiz
,也级联Option
@Size(min = 2)
@OneToMany(mappedBy = "quiz", cascade = CascadeType.ALL)
private List<Option> options;
【讨论】:
它成功了,谢谢。我完全监督,CascadeType 被教授,但我不明白它必须明确声明。我虽然得到了一个不寻常的 JSON 响应,但它似乎是在响应中递归地添加返回的测验。我将在主帖中发布一个 sn-p。 这不是休眠问题。那是杰克逊的问题。看到这个答案***.com/questions/62623483/… 如果遇到困难请告诉我以上是关于使用 @OneToMany 和 @ManyToOne 注释是更新一个实体表,而不是许多表的主要内容,如果未能解决你的问题,请参考以下文章
EclipseLink 如何使用两个@OneToMany 和@ManyToOne 来替换@ManyToMany
使用 OnetoMany 和 ManytoOne 映射时的无限递归循环(双向)
@JoinFormula 和 @OneToMany 定义 - 糟糕的文档
在 Spring Boot 和 PostgreSQL 中使用 OneToMany 关系