@OneToOne 入门
几个问题
- 什么是级联操作?
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Entity(name = "testReport")
@EntityListeners(AuditingEntityListener.class)
public class Report extends BaseUUID1AuditingEntity implements Serializable {
@Column(length = 50)
private String name;
@Column
private Integer size;
@OneToOne
private ReportDay reportDay;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Entity(name = "testReportDay")
@EntityListeners(AuditingEntityListener.class)
public class ReportDay extends BaseUUID1AuditingEntity implements Serializable {
@Column(length = 50)
private String dayName;
@Column
private Integer daySize;
@OneToOne
@JoinColumn(name = "report_id", nullable = false)
private Report report;
}
级联保存操作
// ReportDay
@OneToOne
@JoinColumn(name = "report_id", nullable = false)
private Report report;
// ======== service ===========
val reportDayModel = model.getReportDay();
ReportDay reportDay = null;
Report report = null;
// =======方式1=======
report = Report.builder()
.name(model.getName())
.size(model.getSize())
// .reportDay(reportDay)
.build();
reportDay = ReportDay.builder()
.dayName(reportDayModel.getDayName())
.daySize(reportDayModel.getDaySize())
.report(report)
.build();
// reportRepository.save(report);
reportDayRepository.save(reportDay);
// =========方式2========
reportDay = ReportDay.builder()
.dayName(reportDayModel.getDayName())
.daySize(reportDayModel.getDaySize())
// .report(report)
.build();
report = Report.builder()
.name(model.getName())
.size(model.getSize())
.reportDay(reportDay)
.build();
// reportDay.setReport(report);
reportRepository.save(report);
// reportDayRepository.save(reportDay);
当两边只使用@OneToOne会创建表,并且会建外键,保存会报错,说明@JoinColumn
只是控制,不是说没有就不增加字段
当ReportDay
增加@JoinColumn
配置,保存报错:Not-null property references a transient value - transient instance must be saved before current operation
当Report
增加@OneToOne(mappedBy = "report")
,仍报上面的错,但是我们发现Report
所在的表没有report_day_id
字段了,已经委托给ReportDay
管理关系了,双向关联时,需要配置它,否则数据库表会多生成一个外键关联,当做级联新增PERSIST时,会为空
当Report
增加@OneToOne(mappedBy = "report", cascade = CascadeType.PERSIST)
保存失败,需要在保存之前reportDay.setReport(report);
当ReportDay
增加@OneToOne(cascade = CascadeType.PERSIST)
ReportDay
级联Report
保存成功,说明cascade
配置在哪个类上,该类save时,级联保存配置在该类下的JPA。
小结:级联可以在两边save,但是如果在mappedBy所在的JPA上级联保存,需要关联实体做双向set。而在委托JPA上做级联保存,则只需要将被委托JPA set 到委托JPA上即可,这也符合委托的含义(被委托JPA上的委托JPA在数据库上不存在,只是JPA层面的关系)
级联删除在委托方可以删除吗?被委托方删除可以理解
orphanRemoval = true 与 级联删除