簡體   English   中英

JPA雙向1..N關聯,避免在子級中查詢以設置父級

[英]JPA bidirectional 1..N association, avoid querying in child to set parent

我正在將Spring Data JPA + Hibernate用於Web應用程序。 對於特定的域模型A,我們在另一個域B中具有一對多關聯。這樣,A將具有Set getB(),而B將具有A getA()。

查詢A圖時,我看到休眠狀態正在使用1 + n查詢。 單個外部聯接查詢用於獲取A圖,但隨后的'n'查詢用於在每個B中設置A。

我在這里錯過任何模式嗎? 由於所有孩子都具有相同的父母,因此無法避免這些“ n”個查詢嗎?





    @MappedSuperclass
    @Data
    public abstract class Batch implements Serializable {

      private static final long serialVersionUID = 1L;

      @OneToOne(fetch = FetchType.EAGER)
      @JoinColumn(name = "batch_id", referencedColumnName = "batch_id")
      protected BatchID batchId;

    }


    /*
    //The parent class in a simplified form
    */
    @Entity
    @Table(name = "DRYRUN")
    @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
    public class DryrunBatch extends Batch {

      /**
       * 
       */
      private static final long serialVersionUID = -1596595930859735318L;
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      @Getter@Setter
      protected Long id;

      public DryrunTNStatus newTNStatus()
      {
        final DryrunTNStatus tn = new DryrunTNStatus();
        tn.setBatch(this);
        getTnStatus().add(tn);
        return tn;
      }

      @OneToMany(fetch = FetchType.LAZY, mappedBy = "batch")
      @Getter@Setter
      private Set tnStatus = new HashSet();
    }


    //The child class in a simplified form

    @Entity
    @Table(name = "DRYRUN_TN_STATUS")
    @Data
    public class DryrunTNStatus implements Serializable{

      /**
       * 
       */
      private static final long serialVersionUID = -4388406636444350023L;

      public DryrunTNStatus(String accountNo, String telNo) {
        super();

        this.accountNo = accountNo;
        this.telNo = telNo;
      }

      @ManyToOne(fetch = FetchType.LAZY)
      @JoinColumn(name = "BATCH_ID", referencedColumnName = "BATCH_ID")
      private DryrunBatch batch;

      public DryrunTNStatus()
      {

      }
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      protected Long id;

    }

使用JpaRepository獲取對象圖的代碼。 使用Spring JPA支持來實施外部聯接。 我比Hibernate的@Fetch注釋更喜歡它。



    DryrunBatch drBatch = drBatchRepo.findOne(new Specification() {

          @Override
          public Predicate toPredicate(Root root, CriteriaQuery query,
              CriteriaBuilder cb) {
            query.distinct(true);
            root.fetch("tnStatus", JoinType.LEFT);
            return cb.equal(root.get("batchId").get("id"),
                batch.getId());

          }
        });

最后是來自日志的休眠查詢。 我正在運行一個junit,該junit從DB獲取一個帶有10個孩子的父母。



    //this query can fetch data for the complete graph??
    Hibernate: select distinct dryrunbatc0_.id as id1_6_0_, tnstatus1_.id as id1_9_1_[etc..] from dryrun dryrunbatc0_ left outer join dryrun_tn_status tnstatus1_ on dryrunbatc0_.batch_id=tnstatus1_.batch_id where dryrunbatc0_.batch_id=15

    //and then 10 queries like
    Hibernate: select dryrunbatc0_.id as id1_6_3_, [etc..] from dryrun dryrunbatc0_ left outer join batch_id batchid1_ on dryrunbatc0_.batch_id=batchid1_.batch_id inner join users user2_ on dryrunbatc0_.created_by=user2_.login_id left outer join dryrun_tn_status tnstatus3_ on dryrunbatc0_.batch_id=tnstatus3_.batch_id where dryrunbatc0_.batch_id=?

您在懶加載中遇到了著名的N + 1問題。 沒有JPA標准的方法可以解決此問題,但是,每個JPA提供程序都提供了打開“批量提取”的方法,該方法將立即加載所有惰性引用,而不是在單個SQL查詢中加載每個惰性引用。

這是有關如何在休眠狀態下打開它的信息。

這是一篇文章 ,解釋了如何使用eclipselink進行批量獲取以及示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM