簡體   English   中英

在數據庫中存儲以Java列表表示的“大”數據的最佳實踐是什么?

[英]What is a best practice to store 'large' data, represented by List in Java, in database?

在數據庫中存儲以Java列表表示的“大”數據的最佳實踐是什么?

我正在考慮3個變體:

  1. 使用“ @OneToMany”將數據存儲在單獨的表中。
  2. 序列化數據並將其存儲在父表中。
  3. 將數據存儲為文件(命名約定?與id相同?)。

更加具體

“大”數據實體:

class SingleSleeper{

    private Double startPositionOnLeft;
    private Double endPositionOnLeft;
    private Double startPositionOnRight;
    private Double endPositionOnRight;
....
}

class RutEntry{

    private Double width;
    private Double position;
...
}

一個父實例中大約有50個SingleSleeper類實例,大約25000個RutEntry類實例。 父實例每天生成約40次。 我正在使用EclipseLink JPA 2.1,derby

加成

最重要的是,我對Java的最佳可讀性感興趣。 但是,如果我將太多數據存儲到數據庫中,恐怕數據庫速度會大大降低。 大量請求將是選擇特定父實體的SingleSleeper或RutEntry類的所有實例。 我對支持不同的數據庫類型不感興趣,但是如果需要,我可以移至其他數據庫。

我想我不會做您的任何變體。

我會向ManyToOne添加一個ManyToOne (這在某種程度上與您的第一個變體相反):

public class SingleSleeper {
   @ManyToOne(optional = false, fetch = FetchType.LAZY)
   private ParentEntity parent;

   ...
}

public class RutEntry {
   @ManyToOne(optional = false, fetch = FetchType.LAZY)
   private ParentEntity parent;

}

這樣可以確保您具有映射,並且如果不需要父對象,則永遠不會為其加載所有25000個實體(延遲提取可確保您甚至不需要加載父實體)。

如果確實需要, 可以在帶有mappedBy鏈接的父對象中創建一個OneToMany 例如,由於您始終需要父實體中的所有子對象:

class ParentEntity {
    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    Collection<SingleSleeper> singleSleepers;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    Collection<RutEntry> rutEntries;
}

但是我不知道EclipseLink在這里如何工作-對於Hibernate,您至少需要一個附加的BatchSize批注,以指示它應該一次加載盡可能多的子實體。 它不能與父實例一起獲取所有內容(例如,通過將兩者都定義為FetchType.EAGER ),因為只允許熱切地獲取其中一個(否則,對應的SQL結果集中將有25000 * 50個結果行)選擇語句)。

為父實體加載所有子實體的最佳方法是使用JPQL (易於閱讀,編寫速度更快)或Criteria API (類型安全,但需要元模型 )分別加載它們:

ParentEntity parent = entityManager.find(ParentEntity.class, id);

// JPQL:
List<SingleSleeper> singleSleepers = entityManager.createQuery(
   "SELECT s FROM SingleSleeper s WHERE s.parent = %parent"
   ).setParameter("parent", parent).getResultList();

// Or Criteria API:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<SingleSleeper> query = criteriaBuilder.createQuery(SingleSleeper.class);
Root<SingleSleeper> s = query.from(SingleSleeper.class);
query.select(s).where(criteriaBuilder.equal(s.get(SingleSleeper_.parent), parent));
List<SingleSleeper> singleSleepers = entityManager.createQuery(query).getResultList();

該方法具有三個優點:

  1. 仍然易於閱讀-如果您將加載放入自己的方法中。
  2. 您可以靈活地決定何時加載25050個子級。
  3. 您也可以加載子項的子集(通過使用Query.setFirstResultQuery.setMaxResults修改createQuery的結果)。

暫無
暫無

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

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