Hibernate 无需生成外键即可使用单个映射表建立多个关系

发布于 2024-12-03 02:39:20 字数 1612 浏览 4 评论 0原文

我有两个基本抽象类,并且有多个从这两个抽象类派生的附加类,添加附加属性等。

这些特定的派生类型之间存在关系。

一个简单的说明示例:

RoleGroup 类是 abstract,但它们没有标记为 @映射的超类

正在使用 InheritanceType.JOINED 策略,因此表 Role (对于抽象类)和 AdminRole (对于派生类)都应该存在(它们都将具有相同的RoleID)。

  • DiscussionGroup 有一个 AdminRole 属性,一个 SetSet
  • WorkingGroupSetSet<经理角色>
<前><代码>角色 |-- 管理员角色 |-- 讨论者角色 |-- 经理角色 |-- 工人角色 团体 |-- 讨论组 |-- 工作组

因为派生类的数量可能会增长,并且因为从 Role 派生的类可以与从 Group 派生的不同类有关系(反之亦然),这将导致大量不同的映射表(Worker_DiscussionGroup、Worker_WorkingGroup)或多个外键列(在 M:1 关系中 - 例如 ManagerRole 必须具有 DiscussionGroupID 和workingGroupId)。 我想通过一个通用映射表来映射所有这些关系。

Role_Group (RoleID, GroupId)

在当前开发过程中,我们使用Hibernate 生成 DDL 架构 (hbm2ddl.auto=create)(我们将使用静态模式定义供以后生产使用)。 Hibernate 会自动为关系创建外键,这对我们来说非常好。

如果我指示它使用相同的映射表进行连接(对于多对多、多对多以及一对一),它将尝试创建外键也是如此。当然,不可能在从 Role_GroupAdminRoleDiscussantRoleRoleID 上创建外键同时,所以我收到错误。

有什么方法,如何指示 Hibernate

  1. 在没有外键的情况下生成选定的关系

  2. 定义关系应基于抽象 祖先(即 DiscussionGroup 及其 Set 应该 映射为 1:N - 组和集合)?

I have two base abstract classes and there are multiple additional classes derived from these two, adding additional attributes etc.

There exist relations between those specific derived types.

A simple illustrating example:

Role and Group classes are abstract, but they are not marked as @MappedSuperclass.

InheritanceType.JOINED strategy is being used, so both tables Role (for abstract class) and AdminRole (for derived class) should exist (they both will have the same RoleID).

  • DiscussionGroup has one AdminRole property, a
    Set<DiscussantRole>, a Set<ManagerRole>
  • WorkingGroup has Set<WorkerRole>, Set<ManagerRole>
Role 
|-- AdminRole
|-- DiscussantRole
|-- ManagerRole
|-- WorkerRole

Group
|-- DiscussionGroup
|-- WorkingGroup

Because the number of derived classes can grow, and because classes derived from Role can have relations to different classes derived from Group (and vice versa) this would lead to a large amount of different mapping tables (Worker_DiscussionGroup, Worker_WorkingGroup) or multiple foreign key columns (in M:1 relationships - e.g. a ManagerRole would have to have DiscussionGroupID and WorkingGroupId). I want to map all these relations through one common mapping table.

Role_Group (RoleID, GroupId)

We use Hibernate to generate the DDL schema (hbm2ddl.auto=create) during current development (we will use a static schema definition for later production use). Hibernate automatically creates Foreign keys for the relations, and thats quite good for us.

If I instruct it to use the same mapping a table for joins (for the many-to-many, many-to-many and for one-to-one as well), it will try to create foreign keys as well. And it is of course not possible to create a foreign key on RoleID from Role_Group to AdminRole and DiscussantRole at the same time, so I get an error.

Is there any way, how to instruct Hibernate

  1. to generate selected relationships without foreign keys

    or

  2. to define that the relation should be based on the abstract
    ancestors (i.e. DiscussionGroup and its Set should
    be mapped as 1:N - Group and Set)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绳情 2024-12-10 02:39:20

以下对我来说是问题 2 的答案:

@ForeignKey( name = "none" )

没有为该关系生成外键。

@Cascade( value = { CascadeType.ALL } )
@OneToOne( fetch = FetchType.EAGER, orphanRemoval = true )
@JoinTable( name = "Role_Group",
            inverseJoinColumns = { @JoinColumn( referencedColumnName = "rolleId", name = "RolleID" ) },
            joinColumns = { @JoinColumn( referencedColumnName = "groupId", name = "GroupID" ) } )

@ForeignKey( name = "none" )
public AdminRole getAdmin()

来源:

根据来源,这是一个未记录的功能,可以在发行说明中看到:

Changes in version 2.1.9 (xx.x.xxxx)
------------------------------------
* TimesTenDialect now supported (look at TimesTenDialect for certain limitations)
* foreign-key="none" can be used to disable generation of a foreign key.

在 xml 配置中 - 您可以像

<many-to-one name="Hospital" column="hospitalId" property-ref="hospitalId" update="false" insert="false" foreign-key="none">

让 Hibernate 连接您的世界!(请参阅页面源 - 页面上未显示 xml 配置)

注意:

但这并不能解决整个问题。 Hibernate 也无法通过此映射表为 getAdmingetManagers 获取正确的数据,因为它会查找 Role_Group,找到 RoleIDs< /code> for DiscussionGroup GroupID 并且不知道它是用于 AdminRole 还是 ManagerRole 并给出“ 没有给定的行标识符存在“错误”,

但是当我在 Group 或 DiscussionGroup 中使用此类表作为 public SetgetRoles() 时,Hibernate 将成功加载派生类 (AdminRoleManagerRole)到集合。

Following works for me as an answer for question number 2:

@ForeignKey( name = "none" )

No foreign key is being generated for the relationship.

@Cascade( value = { CascadeType.ALL } )
@OneToOne( fetch = FetchType.EAGER, orphanRemoval = true )
@JoinTable( name = "Role_Group",
            inverseJoinColumns = { @JoinColumn( referencedColumnName = "rolleId", name = "RolleID" ) },
            joinColumns = { @JoinColumn( referencedColumnName = "groupId", name = "GroupID" ) } )

@ForeignKey( name = "none" )
public AdminRole getAdmin()

Sources:

Based on the sources, it is an undocumented feature which was seen in release notes:

Changes in version 2.1.9 (xx.x.xxxx)
------------------------------------
* TimesTenDialect now supported (look at TimesTenDialect for certain limitations)
* foreign-key="none" can be used to disable generation of a foreign key.

In xml config - you would use it like this

<many-to-one name="Hospital" column="hospitalId" property-ref="hospitalId" update="false" insert="false" foreign-key="none">

as mentioned in Let Hibernate Connect Your World! (see the page sources - xml configuration is not shown on the page)

Note:

This does not solve the whole problem however. Hibernate cannot get the right data through this mapping table for getAdmin and getManagers as well, because it looks to Role_Group, finds RoleIDs for DiscussionGroup GroupID and has no idea if it is for AdminRole or ManagerRole and gives "No row with the given identifier exists" error".

Simimilar mapping works however when I use such table in Group or DiscussionGroup as public Set<Role> getRoles(), Hibernate will successfully load derived classes (AdminRole, ManagerRole) to the Set.

且行且努力 2024-12-10 02:39:20

我认为你应该保留多张桌子。它只是映射类中存在的关系。

如果您不希望这样,那么您可以在抽象 Group 中定义一个 Set 并在抽象 Group 中定义一个 Set >角色。子类中不会有任何“子集”;您只需使用正确类型的适当元素填充抽象类中的集合即可。然后,自动映射将为您提供您想要的单个连接表。

I think that you should keep multiple tables. It just maps the relationship that exists in your classes.

If you don't want that then you could define a Set<Role> inside abstract Group and a Set<Group> in abstract Role. You would not have any "subsets" in the subclasses; you just fill the set from the abstract class with the appropriate elements of the right type. The automatic mapping would then give you a single join table like you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文