如何在 Hibernate 中创建多态/通用多对多关系?

Posted

技术标签:

【中文标题】如何在 Hibernate 中创建多态/通用多对多关系?【英文标题】:How to create polymorphic/generic many-to-many relationship in Hibernate? 【发布时间】:2013-09-29 06:18:07 【问题描述】:

我想创建一个通用的多对多关系(列表)。

使用以下示例域:

+-------+  +----------+ +-----------+
| Issue |  | Web Page | | Wiki Page |  
+-------+  +----------+ +-----------+

我想创建一个如下所示的通用链接关联,其中fromto 可以是上面的任何域对象。

+---------------------+ 
| Link                |
+---------------------+ 
| Object: from        |
| Object: to          |
| String: description |
+---------------------+ 

所以Issue has-many Link,问题出在关系的一侧。

我设想使用如下所示的链接表:

Link Table
| ID | SRC_ID | SRC_CLASS | DEST_ID | DESC_CLASS |

所以SRC_IDDEST_ID 是相应表的外键。

Link 表的映射应该是什么样的?

【问题讨论】:

【参考方案1】:

Hibernate 中,您不应从Entity 类手动创建表。只需将注解@ManyToMany 放到您的pojo 中,hibernate 就会生成您的数据库架构,其中包含您与相关表的所有外键关系。

Hibernate 多对多单向映射应该是这样的:

@Entity
class Issue
  @ManyToMany
  List<Link> links;


@Entity
class Link

如果您的应用程序是 Java SE,则使用 SchemaExport 类在数据库中生成架构。

【讨论】:

是的,我明白这一切 - 但添加表格结构示例的原因是为了让您了解我在寻找什么。由于关系的tofrom 末端可以是多种类型,我不确定如何对链接本身进行编码【参考方案2】:

我通过完全从域对象外部化它来实现这种关系。

示例(Groovy+Grails)

class Link
   String fromClass
   long fromId
   String toClass
   long toId
   String description

   Link()
   Link(Object src, Object dest, String descrption)
      fromClass=src.class.name
      fromId=src.id
      toClass=dest.class.name
      toId=dest.id
      this.description=description
   

   Object getFrom()
      // Invoke GORM static finder
      Class.forName(fromClass)."get"(fromId)
   

   Object getTo()
      // Invoke GORM static finder
      Class.forName(toClass)."get"(toId)
   

使用关联的服务层来创建/检索对象:

import org.springframework.transaction.annotation.Transactional
class LinkableService 
  @Transactional
  public void link(Object src, Object dest, String description)
    Link link = new Link(src,dest,description)
    link.save()
  

  @Transactional(readOnly=true)
  public Collection<Link> links(Object subject)
    def fromLinks = Link.findAllWhere(fromClass:subject.class.name, fromId:subject.id)
    def toLinks = Link.findAllWhere(toClass:subject.class.name, toId:subject.id)
    def allLinks = new ArrayList<Link>(fromLinks)
    allLinks.addAll(toLinks)
    return allLinks
  


我有点担心性能,但由于我只希望使用小型数据集,所以这应该不是主要问题。如果没有指标,我还不会优化!

但是有更好的解决方案吗?

【讨论】:

以上是关于如何在 Hibernate 中创建多态/通用多对多关系?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建如何在 typeorm 中创建多对多关系,[NestJS]

如何在实体框架中创建多对多映射?

如何在rails的同一个表中创建多对多

如何使用 schema.graphql 在放大数据存储中创建多对多关系

在 Doctrine 中创建多对多关系的最佳实践。

Prisma:在显式多对多关系中创建或连接记录