【问题标题】:Complete delete and Insert throwing flushing exception完成删除和插入抛出刷新异常
【发布时间】:2017-09-01 01:24:56
【问题描述】:

我有一个问题,需要执行完全删除然后插入。 尝试了一种方法,能否提出其他更好的方法?

{   
  "incidentTime": 1491207083634,
  "estCode": 152,
  "incidentParamTrans": [
    {      
      "paramValueList": [
        11,
        12,
        14
      ]
    }
  ]
}

这是主要的实体类。

@Entity
@Table(name="IR_TB_INCIDENT_HDR")
public class IncidentHdr implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="IR_TB_INCIDENT_HDR_INCIDENTID_GENERATOR", sequenceName="IR_SEQ_INCIDENT_ID")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="IR_TB_INCIDENT_HDR_INCIDENTID_GENERATOR")
    @Column(name="INCIDENT_ID")
    private long incidentId;

    @OneToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REMOVE}, fetch = FetchType.LAZY,  mappedBy="incidentHdr")
    private Set<IncidentParamTran>  incidentParamTrans;

    public IncidentHdr() {
    }

}

这是具有一对多映射的实体类。其中 DTO(来自请求 json)中的这个 paramValueList 被提取并作为 3(paramId) 记录插入 IncidentParamTrans 表中。

/**
 * The persistent class.
 * 
 */
@Entity
@Table(name="IR_TB_INCIDENT_PARAM_TRAN")
public class IncidentParamTran implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="IR_TB_INCIDENT_PARAM_TRAN_GENERATOR", sequenceName="IR_SEQ_INCIDENT_PARAM_RUN_ID")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="IR_TB_INCIDENT_PARAM_TRAN_GENERATOR")
    @Column(name="PARAM_RUN_ID")
    private long paramRunId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="INCIDENT_ID")
    private IncidentHdr incidentHdr;


    @Column(name="PARAM_ID")
    private BigDecimal paramId;


    public IncidentParamTran() {
    }


}

如果输入是这样的。

{   
  "incidentId": 4700,
  "incidentTime": 1491207083634,
  "estCode": 152,
  "incidentParamTrans": [
    {      
      "paramValueList": [
        10,
        14,
      ]
    }
  ]
}

必须删除 IncidentParamTrans 表中的所有数据,事件 ID 为 4700。其中事件 ID 不是主键。

之后,我必须将所有新记录(2 条记录)插入 IncidentParamTrans。

执行完全删除并执行新插入,这又会引发刷新异常。

我尝试过的代码

服务层代码sn-p

@Override
    @Transactional(rollbackFor=IncidentReportingException.class)
    public IncidentHdrDto saveIncidentReport(IncidentHdrDto incidentHdrDto)
    if(incidentHdrDto.getIncidentParamTrans()!= null ){
            Set<IncidentParamTranDto> incidentParamTranDtos = new HashSet<IncidentParamTranDto>();
        //  dto.getSensitivityPattern().remove
            IncidentHdr inc = mapper.map(incidentHdrDto, IncidentHdr.class);
            incidentParamTransRepo.deleteByIncidentHdr(inc);

            for(IncidentParamTranDto item:incidentHdrDto.getIncidentParamTrans()){

                if(item != null){
                    for(BigDecimal paramItem: item.getParamValueList()){
                        IncidentParamTranDto val = new IncidentParamTranDto();
                        val.setParamId(paramItem);
                        val.setIncidentHdr(incidentHdrDto);
                        incidentParamTranDtos.add(val);
                    }
                }
            }
            incidentHdrDto.setIncidentParamTrans(incidentParamTranDtos);
        }

        result = saveIncidentHdr(incidentHdrDto);
        }

将 dto 映射到实体并调用 repo save 方法。

    @Override
    public IncidentHdrDto saveIncidentHdr(IncidentHdrDto incidentHdrDto)
            throws IncidentReportingException {
        return mapper.map(iReportingRepo.save(mapper.map(incidentHdrDto, IncidentHdr.class)),IncidentHdrDto.class);
    }

Repo class used to delete 

    public interface IncidentParamTransRepo extends JpaRepository<IncidentParamTran, Long> {



    Long deleteByIncidentHdr(IncidentHdr inc);

}

例外:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: om.gov.moh.irs.model.entity.incident.IncidentHdr

【问题讨论】:

    标签: java jpa spring-data spring-data-jpa jpa-2.0


    【解决方案1】:

    我认为它失败是因为 IncidentHdr.incidentParamTrans 集合仍然处于无效状态,因为事件参数的实际删除是由 incidentParamTransRepo.deleteByIncidentHdr(inc); 存储库调用处理的,但另一方面,CRUD 操作的所有权是通过级联行为配置在IncidentHdr.incidentParamTrans 上设置。

    为避免混淆,我建议尝试以下方法:

    1. 首先将“IncidentHdr.incidentParamTrans”转换为 DTO 以备后用
    2. 清除IncidentHdr.incidentParamTrans 集合:inc .getIncidentParamTrans().clear()
    3. 使用刷新保存IncidentHdrincidentHdrRepository.**saveAndFlush**(inc)。这将触发您通过手动存储库调用执行的删除查询。使用 flush 执行保存非常重要,因此在再次填充集合之前执行实际的删除查询。
    4. 再次填写“IncidentHdr.incidentParamTrans”并持久化/保存

    这种方法的优点是 Hibernate 可以跟踪对 IncidentHdr.incidentParamTrans 集合所做的所有更改,并确保正确处理状态。 这种方法的一个缺点是它将整个IncidentHdr.incidentParamTrans 集合加载到内存中,但是,根据您的配置,我相信这应该不是问题,因为您已经这样做了(通过委派IncidentHdr.incidentParamTrans 的CRUD 管理到IncidentHdr 实体)。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 2019-02-08
      • 1970-01-01
      • 2017-09-30
      相关资源
      最近更新 更多