#Hibernate need to save every object that is part of a composite key before saving the one that contains it?

I have 3 objects. To call it A, B, C and the fourth, which has a composite key, which is a combination of identifiers.

@Entity public class A { @Id @GeneratedValue(generator = "generator") private String id; } @Entity public class B { @Id @GeneratedValue(generator = "generator") private String id; } @Entity public class C { @Id @GeneratedValue(generator = "generator") private String id; @OneToMany(cascade = CascadeType.ALL, mappedBy = "c", fetch = FetchType.LAZY) private List<ClassWithCompositeKey> relations = new ArrayList<ClassWithCompositeKey>(); } @Entity public class ClassWithCompositeKey { @EmbeddedId protected CompositeKey compositeKey; @JoinColumn(name = "A_ID", insertable = false, updatable = false) @ManyToOne(optional = false) private A a; @JoinColumn(name = "B_ID", insertable = false, updatable = false) @ManyToOne(optional = false) private B b; @JoinColumn(name = "C_ID", insertable = false, updatable = false) @ManyToOne(optional = false) private C c; public ClassWithCompositeKey(A a, B b, C c) { this.a = a; this.b = b; this.c = c; this.compositeKey = new CompositeKey(a.getId(),b.getId(),c.getId()); } } @Embeddable public class CompositeKey { @Basic(optional = false) @Column(name = "A_ID", columnDefinition = "raw") private String aId; @Basic(optional = false) @Column(name = "B_ID", columnDefinition = "raw") private String bId; @Basic(optional = false) @Column(name = "C_ID", columnDefinition = "raw") private String cId; public CompositeKey(String aId, String bId, String cId) { this.aId = aId; this.bId = bId; this.cId = cId; } } 

Then when I try to save:

 A a = new A(); B b = new B(); C c = new C(); entityManager.persist(a); entityManager.persist(b); //I'm not saving C ClassWithCompositeKey classWithCompositeKey = new ClassWithCompositeKey(a, b, c); c.getRelations().add(classWithCompositeKey); entityManager.persist(c); 

I get an exception "ConstraintViolationException: Column 'C_ID' cannot be null"

This is because c.id is null before the c value is saved, but this value refers to an instance of CompositeKey.

I would like to save the "c" and automatically save the collection of ClassWithCompositeKey. However, now I first need to save the "c", then attach an instance of ClassWithCompositeKey to it and save it. Is it possible (possibly using a different type of mapping) that C and ClassWithCompositeKey are cascaded in the same "persistent" call?

+4
source share
3 answers

Only during save will you get the generated value in C, which throws an exception.

Beacuse hibernate will only update the generated value after an insert operation. It first inserts and then updates the join column.

In the above scenario, you have the C_ID of class c, which is the primary key mapped to the C_ID of class ClassWithCompositeKey, which is again the main key, and the primary key cannot be null.

So, try reconnecting the ClassWithCompositeKey class with the foreign key columns.

0
source

You may have to adjust the cascade options in the composite key fields to at least cascade the persist operation.

0
source

I think the problem is that you mark some columns as "insertable = false" and as "optional = false" at the same time in the ClassWithCompositeKey class.

 @JoinColumn(name = "A_ID", insertable = false, updatable = false) @ManyToOne(optional = false) private A a; 

You don't even need these columns! delete the columns a, b and c in this class, you already have them in your built-in identifier, if you need them:

 ClassWithCompositeKey yourClass = ...; //any initialization code yourClass.getCompositeKey().getA(); yourClass.getCompositeKey().getB(); yourClass.getCompositeKey().getC(); 
0
source

All Articles