在数据库中存储 'large' 数据(由 Java 中的列表表示)的最佳做法是什么?

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

在数据库中存储 'large' 数据(由 Java 中的列表表示)的最佳做法是什么?

我正在考虑 3 种变体:

  1. 使用“@OneToMany”将数据存储在单独的 table 中。
  2. 序列化数据并将其存储在父级中table。
  3. 将数据存储为文件(命名规则?与 id 相同?)。

To be more specific

'Large' 数据实体:

class SingleSleeper{

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

class RutEntry{

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

在一个父实例中有大约 50 个 SingleSleeper class 实例和大约 25000 个 RutEntry class 实例。父实例每天生成约 40 次。 我正在使用 EclipseLink JPA 2.1,derby

Addition

最重要的是,我对 Java 中的最佳可读性感兴趣。但是如果我将太多数据存储到数据库中,我担心数据库速度会显着降低。绝大多数请求将针对 select 特定父实体的 SingleSleeper 或 RutEntry class 的所有实例。我对支持不同的数据库类型不感兴趣,但如果需要,我可以转移到其他数据库。

我想我不会做你的两种变体。

我会向 child 实体添加一个 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;

}

这确保您有一个映射,并且如果您不需要它们,您从不加载 parent object 的所有 25000 个实体(延迟获取确保您甚至不需要加载 parent 实体)。

可以在parentobject中创建一个OneToManymappedBylink,如果你真的想要。例如,因为您始终需要 parent 实体中的所有 child object:

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

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

但我不知道 EclipseLink 在这里是如何工作的 - 对于 Hibernate,您至少需要一个额外的 BatchSize 注释来指示它应该一次加载尽可能多的 child 实体。它不能与 parent 实例一起获取(例如,通过将两者定义为 FetchType.EAGER),因为只允许急切获取一个(否则你将有 25000 * 50 个结果行在SQL select语句对应的结果集).

为 parent 实体加载所有 child 实体的最佳方法是单独加载它们,或者使用 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. 你可以灵活决定什么时候加载25050children。
  3. 您也可以加载 children 的子集(通过使用 Query.setFirstResultQuery.setMaxResults 修改 createQuery 的结果)。