我正在尝试将历史记录实体保存到数据库。在该实体上还有一个导致问题的“ trackerId”。历史记录表:
@Entity
@Table(name = "History")
public class History {
private static final long serialVersionUID = 3729158137942963422L;
@Id
@GeneratedValue
private Long id;
@Column(name = "absenceStatus")
private Integer absenceStatus;
@ManyToOne( fetch = FetchType.EAGER )
@JoinColumn(name = "absenceTypeId", nullable = false )
@ForeignKey(name = "FK_History_AbsenceType")
private AbsenceType absenceType;
@ManyToOne( fetch = FetchType.EAGER )
@JoinColumn(name = "weekId", nullable = false )
@ForeignKey(name = "FK_History_WeeklyOverview")
private WeeklyOverview weeklyOverview;
@ManyToOne( fetch = FetchType.EAGER )
@JoinColumn(name = "trackerId" )
@ForeignKey(name = "FK_History_Tracker")
private WeeklyOverviewTracker weeklyOverviewTracker;
...
我在代码中正在做什么: 保存WeeklyOverview和WeeklyOverviewTracker。之后(提交完成),我得到了先前保存的WeeklyOverviewTracker实体,并将其添加到WeeklyOverview上。然后在History实体的save方法中将此WeeklyOverview作为参数传递。在保存历史记录之前,我要从WeeklyOverview中读取WeeklyOverviewTracker实体,并将其添加到History实体中。 WeeklyOverviewTracker的ID不为空,并且具有正确的ID。
我真的看不到问题,尤其是因为ID是在WeeklyOverviewTracker上设置的。
如果我向@JoinColumn(name =“ trackerId”)添加'nullable = false',那么在保存时会出现此错误:
TransientPropertyValueException:非null属性引用一个 瞬态值-瞬态实例必须在当前之前保存 操作
如果再添加一个Cascade.ALL,我最终将在数据库上获得两个WeeklyOverviewTracker记录...
导致TransientPropertyValueException的代码:非null属性引用一个瞬态值:
private WeeklyOverviewDTO saveWeeklyOverviewDTOWithTracker(...) {
WeeklyOverview weeklyOverview = WeeklyOverviewConverter.from(woDTO);
weeklyOverview = weeklyOverviewDAO.merge(weeklyOverview);
WeeklyOverviewTracker savedWeeklyOverviewTracker = saveWeeklyOverviewTracker(...);
WeeklyOverviewDTO weeklyOverviewDTO = WeeklyOverviewConverter.from(weeklyOverview);
List<WeeklyOverviewTrackerDTO> tmp = new ArrayList<>();
WeeklyOverviewTrackerDTO weeklyOverviewTrackerDTO = WeeklyOverviewTrackerConverter.fromEntity( savedWeeklyOverviewTracker );
tmp.add( weeklyOverviewTrackerDTO );
weeklyOverviewDTO.setWeeklyOverviewTrackerDTOs( tmp );
return weeklyOverviewDTO;
}
此方法完成后,将提交事务,并且新事务将开始保存History实体:
public List<HistoryDTO> save( WeeklyOverviewDTO weeklyOverviewDTO ) {
final List<HistoryDTO> historyDTOs = createHistoryDTOs( weeklyOverviewDTO );
List<History> updatedHistories = new ArrayList<>();
for( final HistoryDTO dto : HistoryDTOs ) {
History updated = transactionWrapper(new IPersistenceExecutable<History>() {
@Override
public History execute() {
boolean contains1 = historyDAO.getEntityManager().contains( entity.getAbsenceType() );
boolean contains2 = historyDAO.getEntityManager().contains( entity.getWeeklyOverview() );
boolean contains3 = historyDAO.getEntityManager().contains( entity.getWeeklyOverviewTracker() );
History merged = historyDAO.merge( HistoryConverter.toEntity( dto ) );
...
和createHistoryDTOs方法只是创建HistoryDTO并在其上设置WO-DTO,AbsenceTypeDTO和WOT-DTO。然后从WO-DTO检索所有这些数据。
我刚刚添加了包含的支票。因此包含1和2都是正确的。包含3个为假。
编辑:
啊,我想我明白了。 HistoryConverter.toEntity( dto )
正在将AbsenceTypeDTO,WeeklyOverviewDTO和WeeklyOverviewTrackerDTO转换为实体,并将其添加到History实体。但是在转换DTO之前,它会检查是否存在ID,如果存在,则调用find()。而WeeklyOverviewTracker缺少该部分...
明天会测试,让您知道...