优化Spring-data / Hibernate ManyToMany插件

时间:2013-09-26 17:13:39

标签: sql spring hibernate optimization query-optimization

我对Hibernate处理插入JoinTable的方式感到有点困惑。

我在JoinTable中需要一些额外的字段,因此我选择了非常常见的方式,为JoinTable创建@Entity并使用@OneToMany@ManyToOne。因为关系应该是唯一的,所以我在JoinTable-Entity中创建了一个@EmbeddedId

让我们拨打课程ABAB

@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中,我只需要执行一个查询即可完成所有操作。如果关系已存在,则数据库将抛出错误。

使用hibernate我需要:

  1. SELECT:为id = A
  2. 提供课程A_id的实例
  3. SELECT:为id = B或id = B_id1或...
  4. 提供课程B_id2的实例
  5. 创建类AB的新实例并设置复合主键并保存AB
  6. 最后一步产生(对于每个AB):

    1. 从AB中选择*,其中a_id = ...和b_id = ...
    2. 插入AB(aId,bId)值(......,...)
    3. 这是我的代码。使用spring数据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();
      

      如果我只是用AB对象创建一个新的ArrayList并且之后立即保存所有这些,或者如果我在上面的代码中那样做,那都没关系。它总是对每个对象进行选择和插入。

      有没有办法用较少的查询来完成?

1 个答案:

答案 0 :(得分:0)

这很奇怪,因为您看到的是saveOrUpdate对于分离对象的行为。 我希望hibernate为AB发出select,如果它们是分离的对象,而不是AB,因为你正在调用save

您可以尝试使用persist来查看它是否发生任何变化。