I have what is becoming a pretty complex entity setup:
A -> (one-to-one, share same primary key) B -> (one-to-many) C
@Entity
public class A {
@Id
@Column(unique = true, nullable = false)
private Long id;
@MapsId
@OneToOne
@JoinColumn(name = "id")
private B b;
}
@Entity
public class B {
@Id
@Column(unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(fetch = FetchType.LAZY, optional = true)
@PrimaryKeyJoinColumn
private A a;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "id")
private Set<C> c;
}
@Entity
public class C {
@Id
@Column(unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
private Long cId;
@MapsId
@ManyToOne
@JoinColumn("id")
private B b;
}
I want to create A, B, and C at the same time. First of all, is this possible? Real quick unit test:
A a = new A();
B b = new B();
C c1 = new C();
c1.setB(b);
C c2 = new C();
c2.setB(b);
Set<C> set = new HashSet<C>(2);
set.add(c1);
set.add(c2); // works if this is commented out
b.setA(a);
b.setC(set);
a.setB(b);
crudRepo.save(a);
DataIntegrityViolationException: A different object with the same identifier value was already associated with the session
I have tried a whole load of combinations with different cascade types, different "ownedBys" and either end up with it trying to generate multiple "C"s with the same ID/primary key, or an error saying C needs to be persisted first. Apologies if I copied over some code incorrectly - tried to keep the irrelevant stuff out.