与单个映射表的多个关系,而不是由Hibernate生成外键

时间:2011-09-05 23:09:12

标签: java hibernate many-to-many one-to-one many-to-one

我有两个基本抽象类,还有多个来自这两个类的附加类,添加了其他属性等。

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

一个简单的说明示例:

RoleGroup类为abstract,但未标记为@MappedSuperclass

正在使用

InheritanceType.JOINED策略,因此两个表Role(对于抽象类)和AdminRole(对于派生类)应该存在(它们都将具有相同的{{1} })。

  • RoleID有一个DiscussionGroup属性,a AdminRoleSet<DiscussantRole>
  • Set<ManagerRole>WorkingGroupSet<WorkerRole>
Set<ManagerRole>

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

Role 
|-- AdminRole
|-- DiscussantRole
|-- ManagerRole
|-- WorkerRole

Group
|-- DiscussionGroup
|-- WorkingGroup

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

如果我指示它使用相同的映射表连接(对于多对多,多对多和一对一),它将尝试创建外来密钥。并且当然不可能同时在Role_Group (RoleID, GroupId) RoleIDRole_GroupAdminRole创建外键,因此我收到错误。

有没有办法,如何指导Hibernate

  1. 生成没有外键的选定关系

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

2 个答案:

答案 0 :(得分:3)

以下作为问题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">

Let Hibernate Connect Your World!中所述(参见页面来源 - 页面上未显示xml配置)

注意:

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

然后,当我在Group或DiscussionGroup中将此类表用作public Set<Role> getRoles()时,相似的映射有效,Hibernate将成功地将派生类(AdminRoleManagerRole)加载到Set。

答案 1 :(得分:1)

我认为你应该保留多个表格。它只是映射你的类中存在的关系。

如果您不希望这样,那么您可以在摘要Set<Role>内定义Group,在摘要Set<Group>中定义Role。你不会在子类中有任何“子集”;您只需使用正确类型的相应元素填充抽象类中的集合。然后,自动映射会为您提供一个单独的连接表。