'ERROR: null value in column "XX" violates not-null constraint SPRING

I have a parent child entity OneToMany relation. When I .save to insert while the identifier is the same, I want it to update.

Here's my service:

@Override
public MsExplodedDTO saveExplodedFactory(MsExplodedFactoryRequestDTO exploded) {
    
    MsProduct prod = msProductRepo.findByProductCode(exploded.getProductCode())
            .orElseThrow(() -> new ResourceNotFound("Data Produk tidak ditemukan!"));

    
    exploded.setProductCode(prod.getId().toString());
    
    MsExploded exp;
    if (explodedRepo.findByExplodedCodeIgnoreCase(exploded.getExplodedCode()).size() > 0) {
        
        MsExploded oldExploded = explodedRepo.findByExplodedCode(exploded.getExplodedCode())
                .orElseThrow(() -> new ResourceNotFound("Data tidak ditemukan!"));
        
        return updateExplodedFactory(exploded, prod);
    }else {
        exp = mapper.DTO2Entity(exploded);
        exp.setId(0L);
        exp.getExplodedDt().forEach(d -> {
            d.setExplodedhd(exp);
        });
        
        return mapper.entity2DTO(explodedRepo.save(exp));
    }
    
}

@Override
public MsExplodedDTO updateExplodedFactory(MsExplodedFactoryRequestDTO exploded, MsProduct prod) {

    MsExploded oldExploded = explodedRepo.findByExplodedCode(exploded.getExplodedCode())
            .orElseThrow(() -> new ResourceNotFound("Data tidak ditemukan!"));

    if (oldExploded.getIsDeleted()) {
        throw new ResourceNotAcceptable("Kode Exploded " + oldExploded.getExplodedCode() + " telah dihapus");
    }

    oldExploded = mapper.updateDTO2Entity(exploded, oldExploded);
    oldExploded.setProduct(prod);
    

    for (MsExplodedDetail exp : oldExploded.getExplodedDt()) {
        exp.setExplodedhd(oldExploded);
    }

    MsExploded obj = explodedRepo.save(oldExploded);

    return mapper.entity2DTO(obj);
}

When I debug to update, it says

ERROR: null value in column "ms_exploded_header_id" violates not-null constraint
Detail: Failing row contains (20, 333, 2, null, null, null, null, null, null, null, null, null, null).

While I already insert the repo as it should, it's no problem in saving a new but when update the parent or child it.

Here's my header entity:

@Data
@Audited
@EntityListeners(AuditingEntityListener.class)
@Entity
@Table(name = "ms_exploded")
@EqualsAndHashCode(callSuper = false, of = "id")
@ToString(of = { "id" })
public class MsExploded extends AuditField implements Serializable {
XX
XX
XX
@OneToMany(mappedBy = "explodedhd", orphanRemoval = true, cascade = CascadeType.ALL)
    private List<MsExplodedDetail> explodedDt = new ArrayList<>();
}

And here's my child entity:

@Data
@Audited
@EntityListeners(AuditingEntityListener.class)
@Entity
@Table(name = "ms_exploded_detail")
public class MsExplodedDetail implements Serializable {
XX
XX
XX
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
    @JsonIgnore
    @ManyToOne(targetEntity = MsExploded.class)
    @JoinColumn(name = "ms_exploded_header_id", referencedColumnName = "id")
    private MsExploded explodedhd;
}

I'm pretty sure when I debug, ms_exploded_header_id is inserted with the header id. But I don't know why it cancelled and returned the error.



Solution 1:[1]

Make sure that MsExploded.explodedDt and MsExplodedDetail.explodedhd are always consistent. I.e. the following assertions should hold:

msExploded.explodedDt.forEach(dt -> assertThat(dt.explodedhd).isEqualTo(msExploded);
assertthat(msExplodedDetail.explodedhd).contains(msExplodedDetail)

I suspect you (or the mapper) leave MsExplodedDetail.explodedhd null when adding a detail to an MsExploded.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jens Schauder