2013-09-26 2 views
0

Я немного смущен тем, как Hibernate обрабатывает вставки в JoinTable.Оптимизация Spring-data/Hibernate ManyToMany Inserts

мне нужны дополнительные поля в JoinTable, поэтому я выбрал довольно распространенный способ, чтобы создать @Entity для JoinTable и использовать @OneToMany и @ManyToOne. И поскольку отношения должны быть уникальными, я создал @EmbeddedId внутри JoinTable-Entity.

Назовём классы A, B и 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;   
} 

Мой Обще дело в том, что я хочу, чтобы вставить несколько новых записей в к JoinTable. Поэтому у меня есть ОДИН A_id и несколько B_ids. В простом SQL я просто делал ОДИН запрос, чтобы все было сделано. Если бы отношение уже существовало, база данных выдаст ошибку.

С спячки мне нужно:

  1. SELECT: дайте мне экземпляр класса A для ид = A_id
  2. SELECT: дайте мне экземпляр класса B для ID = B_id1 или ид = B_id2 или ...
  3. Создайте новый экземпляр класса AB и установите составной первичный ключ и сохраните AB

Последний шаг производит (для каждого AB):

  1. выберите * от AB, где a_id = ... и b_id = ...
  2. вставки в AB (AID, BID) значений (. .., ...)

Вот мой код. Использование 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(); 

Это не имеет значения, если я просто создать новый ArrayList с объектами AB, а затем сохранить их все сразу или, если я это сделать, как в коде выше. Он всегда делает выбор и вставку для каждого объекта.

Есть ли способ сделать это с меньшим количеством запросов?

+0

http://stackoverflow.com/questions/5127129/mapping-many-to-many-association-table-with-extra-columns имеет полезную информацию. –

+0

Нет ничего общего с этими дополнительными запросами, которые должен выполнять Hibernate. –

ответ

0

Это странно, поскольку вы видите поведение saveOrUpdate для отдельного объекта. Я бы ожидал, что спящий режим выйдет на выбор для A и для B, если они были удаленным объектом, но не для AB, как вы звоните save.

Вы можете попробовать persist, чтобы узнать, не изменилось ли оно.

+0

Благодарим вас за ответ. Проблема в том, что я использую spring-data-jpa, который не предоставляет таких методов, как persist или merge. Он имеет только 'save' и' saveAndFlush'. –

+0

Попробуйте реализовать Persistable. См. Http://docs.spring.io/spring-data/jpa/docs/1.4.1.RELEASE/reference/html/jpa.repositories.html#jpa.entity-persistence.saving-entites. –