A really weird problem happen to me, I just solved it after a day. I'm just writing here to try to find out some explanation.
This is my original piece of code, inside a method that fetch some data to be insert or updated in the DB through JPA (.save(soggetto)):
DSoggettoA soggettoA = soggetto.getSoggettoA();
if (soggettoA==null) {
soggettoA = new DSoggettoA();
soggetto.setSoggettoA(soggettoA); //<----- THIS LINE!!!!!!!
soggettoA.setSoggetto(soggetto);
soggettoA.setFkDSoggetto(soggetto.getIdDSoggetto());
}
DettaglioSoggettoMapper.INSTANCE.dettaglioSoggettoAToDSoggettoA(soggettoA,
domande.getDettaglioSoggettoA());
setProvinciaAndComune(soggettoA, domande.getDettaglioSoggettoA()); //Set provincia retrieved through a findBy query
With this code, JPA throws me an Oracle exception, as if the value of provincia is null:
ORA-01400: cannot insert null in ("D_SOGGETTO_A"."FK_T_PROVINCIA")
But if I move the line commented with "THIS LINE!!!" to the really bottom of the code (after the line with setProvinciaAndComune), all works fine.
Why does this happen? In theory if I set the reference of soggettoA inside soggetto it should not matter where or when this happen I only need to do that before persisting the entity, is it right?
Edit 19/09: the error happens only when the rows on DSoggettoA is not existing, but if I move soggetto.setSoggettoA(soggettoA); to the bottom the problem is not popping up:
@Entity
@Table(name="d_soggetto")
@Getter
@Setter
public class DSoggetto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="id_d_soggetto")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idDSoggetto;
@OneToOne(mappedBy="soggetto", cascade=CascadeType.ALL, orphanRemoval = true)
private DSoggettoA soggettoA;
}
@Entity
@Table(name="D_SOGGETTO_A")
@Getter
@Setter
public class DSoggettoA implements Serializable, ProvinciaComune {
private static final long serialVersionUID = 1L;
@Id
@Column(name="FK_D_SOGGETTO")
private Integer fkDSoggetto;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_t_provincia")
private TProvincia provincia;
}
@Entity
@Table(name="t_provincia")
@Getter
@Setter
public class TProvincia implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="id_t_provincia")
private Integer idTProvincia;
@OneToMany(mappedBy = "provincia")
private List<DSoggettoA> soggettoA;
}
//Service method:
@Override
@Transactional
public void foo(final Bar bar) {
// call a method that return existing DSoggetto and populate it with
// DSoggettoA as in the first method that I posted...
soggettoRepository.save(retrieveExistingDSoggetto(bar));
}