【问题标题】:Foreign key of child not added to parent entity when saving, one-to-one保存时子实体的外键不加到父实体,一对一
【发布时间】:2021-10-28 15:03:30
【问题描述】:

我有以下设置:

  • Micronaut 3.x
  • Java 15

我正在尝试更新的实体:

@Setter
@Getter
@Entity
@ToString
@Table(name = "single_choice_question")
public class SingleChoiceQuestion extends OrderedQuestion {
  @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
  private SingleAnswer answer;

  @Override
  public void answer(Answer answer) {
    if (answer instanceof SingleAnswer single) {
        this.answer = single;
    }
    throw new IllegalArgumentException("answer is not of SingleAnswer type");
  }
}

我试图将其子实体作为上述实体的一部分保留:

@Getter
@Setter
@Entity
@Table(name = "single_answer")
public class SingleAnswer extends Answer {
  @OneToOne private AnswerOption choice;
}

所有实体都继承自这个:

@MappedSuperclass
public abstract class BaseEntity {

  @Id
  @GeneratedValue(generator = "system-uuid")
  @GenericGenerator(name = "system-uuid", strategy = "uuid2")
  @Column(updatable = false, nullable = false, length = 36)
  @Type(type = "pkg.UuidUserType") // Maps UUID to SQL VARCHAR.
  private UUID id;

  @Version
  @Column(nullable = false)
  private Integer version;
...
}

基本答案类:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Answer extends BaseEntity {

  @Column(nullable = false)
  private Boolean correct;

}

以下行被执行:


@ReadOnly
public class MyService {

  @Transactional
  public <A extends AnswerDto> A answer(A dto, UUID question) {
    var answer = questionsMapper.toAnswer(dto);
    answer.setCorrect(isCorrect(dto, question));

    var orderedQuestion =
        orderedQuestionRepository
            .findById(question)
            .orElseThrow(() -> new NotFoundException("question", question));

    orderedQuestion.answer(answer, false);
    orderedQuestionRepository.saveAndFlush(orderedQuestion);

    return dto;
  }
}

预期行为: SingleAnswer 实例被持久化,它的 FK 保存在问题的answer_id 列中。

实际行为: SingleAnswer 实例被保留,但其 FK 未保存在问题的 answer_id 列中。它们没有以任何方式连接,因此孤立删除似乎也不起作用。

在检查了hibernate的日志后,我可以看到它只执行insert而不执行update的问题。

另一个观察结果是,当我删除刷新时,孤儿删除确实有效 - SingleAnswer 不会持续存在,尽管 FK 情况仍未解决。

orderedQuestion.answer(answer);
orderedQuestionRepository.save(orderedQuestion);

我看不出这个非常基本的设置有什么问题,任何帮助将不胜感激。

【问题讨论】:

  • 我相信答案的父类很重要:它的 id 是如何初始化的?客户端还是生成?如果生成,使用什么策略?
  • @Lesiak 查看编辑
  • 在这种情况下,我唯一不清楚的是问题和答案是否都插入到相同的事务方法中,或者答案是否添加到现有问题中。在第二种情况下,问题是否在保存时进行管理? (我无法重现它,在每种情况下我都会收到有关问题的更新,正如预期的那样)
  • @Lesiak 这是一个现有的问题和一个新的答案。我还有一个不同的OderedQuestion 子类-MultiChoiceQuestion,它有一个集合(One2Many)而不是单个字段。它通过相同的方法,除了问题中的#answer 方法将答案添加到集合中,而不仅仅是分配。一切都适用于多重。 (见编辑中的完整方法)

标签: java hibernate one-to-one micronaut micronaut-data


【解决方案1】:

这个问题非常简单,@ReadOnly 在某个时候被某人偷偷溜进了班级,我没有注意到

【讨论】:

  • 作为一个 sige 节点 - 如果您的订单是受管理的(确实如此),则不需要 save/saveAndFlush
【解决方案2】:

SingleChoiceQuestion实体中包含指示外键的@JoinColumn注解:

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "answer_id")
private SingleAnswer answer;

【讨论】:

  • 不幸的是,这不起作用。澄清一下,该列实际上在数据库中,值只是null
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 2011-02-01
相关资源
最近更新 更多