Home > Software design >  Foreign key of child not added to parent entity when saving, one-to-one
Foreign key of child not added to parent entity when saving, one-to-one

Time:10-29

I have the following setup:

  • Micronaut 3.x
  • Java 15

Entity I'm trying to update:

@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");
  }
}

Its child entity I'm trying to persist as part of the one above:

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

All entities inherit from this:

@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;
...
}

the base answer class:

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

  @Column(nullable = false)
  private Boolean correct;

}

The below lines are executed:


@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;
  }
}

Expected behaviour: the SingleAnswer instance is persisted, and its FK is saved in the answer_id column of the question.

Actual behaviour: the SingleAnswer instance is persisted, but its FK is NOT saved in the answer_id column of the question. They are not connected in any way, so orphan removal doesn't seem to work either.

After examining hibernate's logs, I can see it only executes the insert and does not do and update on the question.

Another observation is when I remove flushing, orphan removal does work - SingleAnswer doesn't persist, although the FK situation isn't resolved still.

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

I can't see anything wrong with this very basic setup, any help would be appreciated.

CodePudding user response:

Include the @JoinColumn annotation indicating the foreign key in SingleChoiceQuestion entity:

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

CodePudding user response:

The issue was painfully simple, a @ReadOnly sneaked in on a class level at some point by someone, and I didn't notice

  • Related