Issue
I have two tables, A and B (not defined by me, inherited from old legacy software), with the following structure:
A: PK (idA, ente),
B: PK(idB, ente), FK(idA, ente) --> A
I need to use @IdClass/@Id, rather than @Embeddeble/@EmbeddebleId, because @GeneratedValue on id columns.
I'd like to insert a new couple of rows this way:
A a = new A();
a.setEnte('E1');
a = repA.save(a);
B b = new B();
b.setA(a);
b = repB.save(b);
I use Spring Data JPA's repositories class. My best try, was:
@Getter
@ToString
@Setter
@Entity
@Table(name = "address")
@IdClass(BPK.class)
@NoArgsConstructor
public class B implements Serializable{
@ManyToOne
@JoinColumns({
@JoinColumn(name="idA", referencedColumnName="idA", nullable=false, insertable=false, updatable=false),
@JoinColumn(name="ente", referencedColumnName="ente", nullable=false, insertable=false, updatable=false)
})
private A a;
@Id
@org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
@GeneratedValue(generator="incrementGenerator")
@Column(name = "idB", columnDefinition = "int(10)", nullable = false)
private Integer idB;
@Id
@Column(insertable=false, updatable=false, unique=true, nullable=false, length=6)
private String ente;
}
@Getter
@ToString
@Setter
@Entity
@Table(name = "Users")
@IdClass(APK.class)
@NoArgsConstructor
public class A implements Serializable {
@Id
@org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
@GeneratedValue(generator="incrementGenerator")
@Column(name = "idA", columnDefinition = "int(10)", nullable = false)
private Integer idA;
@Id
@Column(name = "ente", columnDefinition = "char(6)", nullable = false)
public String ente;
}
This solution doesn't work, because idA and ente are not inserted in save(b) instruction. If I change insertable=true in the @ManyToOne
lines, there will be error on ente field.
Any suggestions?
Solution
Your b.setA() method could also set this automatically
Thanks to Christian Beikov's suggestion, I found an acceptable solution to the problem. Why it should not infer data directly from the entities is not clear to me.
However, the solution is to force the missing data to be set before persisting using @PrePersist.
The model for B becomes:
@Getter
@ToString
@Setter
@Entity
@Table(name = "address")
@IdClass(BPK.class)
@NoArgsConstructor
public class B implements Serializable{
@ManyToOne
@JoinColumns({
@JoinColumn(name="idA", referencedColumnName="idA", nullable=false, insertable=false, updatable=false),
@JoinColumn(name="ente", referencedColumnName="ente", nullable=false, insertable=false, updatable=false)
})
private A a;
@Id
@org.hibernate.annotations.GenericGenerator(name = "incrementGenerator", strategy = "org.hibernate.id.IncrementGenerator")
@GeneratedValue(generator="incrementGenerator")
@Column(name = "idB", columnDefinition = "int(10)", nullable = false)
private Integer idB;
@Id
@Column(insertable=false, updatable=false, unique=true, nullable=false, length=6)
private String ente;
//New lines (In the real code I used getters, of course) <--
@Column(name = "idA", nullable = false, columnDefinition = "int(10)")
private Integer idA;
@PrePersist
private void init() {
this.ente = a.ente;
this.idA= a.idA;
}
}
Answered By - Tiziano Ruaro
Answer Checked By - Pedro (JavaFixing Volunteer)