I'm a bit confused about the way Hibernate handles inserts into the JoinTable.
I need some extra fields in the JoinTable, so I chose the pretty common way, to create an @Entity
for the JoinTable and use @OneToMany
and @ManyToOne
. And because the relations should be unique I created an @EmbeddedId
within the JoinTable-Entity.
Lets call the classes A
, B
and AB
:
@Entity
public class A implements Serializable {
@OneToMany(mappedBy="a", cascade=CascadeType.ALL, orphanRemoval=true)
private Set<AB> abs;
}
@Entity
public class B implements Serializable {
@OneToMany(mappedBy="b", cascade=CascadeType.ALL, orphanRemoval=true)
private Set<AB> abs;
}
@Entity
public class AB implements Serializable {
@Embeddable
public static class Id implements Serializable {
UUID aId;
UUID bId;
public Id(UUID aId, UUID bId) {
this.aId = aId;
this.bId = bId;
}
}
public AB(A a, B b) {
this.id.aId = a.getId();
this.id.bId = b.getId();
this.a = a;
this.b = b;
}
@EmbeddedId
private Id id;
@MapsId("aId")
@ManyToOne
@JoinColumn(nullable=false, updatable=false)
private A a;
@MapsId("bId")
@ManyToOne
@JoinColumn(nullable=false, updatable=false)
private B b;
}
My commons case is, that I want to insert multiple new entries in to the JoinTable. So I have ONE A_id
and multiple B_ids
. In plain SQL, I'd simply do ONE query to get it all done. If the relation did already exist, the database will throw an error.
With hibernate I need to:
SELECT
: give me an instance of classA
for id =A_id
SELECT
: give me an instance of classB
for id =B_id1
or id =B_id2
or ...- Create a new instance of class
AB
and set the composite primary key and saveAB
The last step produces (for each AB
):
- select * from AB where a_id = ... and b_id = ...
- insert into AB (aId, bId) values (..., ...)
Here's my code. Using spring data jpa (JpaRepository
):
A a = aRepo.findOne(aId);
List<B> bs = bRepo.findAll(bIdList);
for(B b : bs) {
AB ab = new AB(a, b);
abRepo.save(ab);
}
groupUserRepo.flush();
It doesn't matter if I just create a new ArrayList with the AB objects and afterwards save all of them at once or if I do it like in the code above. It always does a select and an insert for each object.
Is there a way to do it with less queries?