Hibernate三个表多对多

时间:2014-03-13 16:13:39

标签: java hibernate jpa

我有一个包含3个表的数据库。主表格为Contract,并且它与两个表格的成对密钥相关联:LanguagesRegions。 每一对都是唯一的,但一个合约可能会有以下一对ID:

{ (1,1), (1,2), (2,1), (2,2) }

今天,这三个表通过名为ContractLanguages的连接实体进行链接。它包含一个序列ID,以及三个表中的三元组ID。 但是,在足够大的合同中,这会导致严重的性能问题,因为hibernate环境会创建大量的对象。 因此,我们希望删除此连接实体,以便Contract收集这些对的一些集合。

我们提出的解决方案:创建一个包含语言和地区ID的@embeddable类,并将它们存储在Contract实体中。 这背后的想法是,语言和地区的数量相对较少。 我们假设hibernate管理这样的对的列表并且不创建重复,因此大大减少了创建的对象的数量。

但是,我们有以下问题:

  1. 此解决方案有效吗? hibernate会知道创建正确的对象吗?
  2. 假设解决方案有效(链接是否正确创建),hibernate会优化对象创建以停止创建重复对象吗?
  3. 如果此解决方案不起作用,我们如何在没有连接实体的情况下解决上述问题?

1 个答案:

答案 0 :(得分:0)

从您的帖子和评论中我假设以下情况,如果我错了,请纠正我:

  • 您有一组有限的Languages + Regions组合(目前建模为ContractLanguages个实体)
  • 您拥有大量Contract个实体
  • 每份合约都可以引用多个LanguagesRegions
  • 您在加载所有合同语言时遇到问题,因为目前该合并包含合同+语言+区域

基于这些假设,我想到了几种可能的优化:

  • 您可以创建一个具有唯一ID的LanguageRegion实体,每个合同都会引用一组。这样你就可以获得一个表,但是Hibernate只会为每个LanguageRegion创建一个实体,并且每个会话加载一次,即使多个合同会引用它。为了使其正常工作,您应该使用延迟加载,并在加载合同之前将这些LanguageRegion实体加载到第一级缓存中。

  • 或者,您可以只加载所需的列,即只加载实体的部分。您也会使用延迟加载,但不会直接访问合同语言,而是在单独的查询中加载它们,例如(名字猜到了)

    SELECT c.id, lang.id, lang.name, region.id, region.name FROM Contract c
     JOIN c.contractlangues cl
     JOIN cl.language lang
     JOIN cl.region region
     WHERE c.id in (:contractIds)
    

    然后加载合同,获取它们的ID,使用该查询加载语言和区域详细信息(它返回一个List<Object[]>,其中包含所选列值的对象数组。将它们放入适当的数据结构中并根据需要访问它们。这样您就可以绕过实体创建并获取所需的数据。