无法将值NULL插入表“ History”的表“ trackerId”中;列不允许为空。 INSERT失败

时间:2018-08-13 11:19:21

标签: hibernate null foreign-keys

我正在尝试将历史记录实体保存到数据库。在该实体上还有一个导致问题的“ trackerId”。历史记录表:

enter image description here 这里是History实体类:

@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缺少该部分...

明天会测试,让您知道...

0 个答案:

没有答案