Multiple relationship with separate mapping table without generating foreign keys using Hibernate

I have two base abstract classes and of them some additional classes added, additional attributes added, etc.

There is a relationship between these specific derived types.

Simple illustrative example:

Role

and Group

classes abstract

, but they are not marked as @MappedSuperclass

.

InheritanceType.JOINED

the strategy is used, so both tables Role

(for the abstract class) and AdminRole

(for the derived class) must exist (both will have the same RoleID

).

  • DiscussionGroup

    has one property AdminRole

    , a Set<DiscussantRole>

    , aSet<ManagerRole>

  • WorkingGroup

    has Set<WorkerRole>

    ,Set<ManagerRole>

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

Group
|-- DiscussionGroup
|-- WorkingGroup

      

Since the number of derived classes can grow, and since classes derived from Roles can have relationships to different classes derived from a group (and vice versa), this will result in many different mapping tables (Worker_DiscussionGroup, Worker_WorkingGroup) or multiple foreign key columns (in M: 1 relationships - for example, the Role manager must have a DiscussionGroupID and a WorkingGroupId). I want to map all these relationships through one common mapping table.

Role_Group (RoleID, GroupId)

      

We use Hibernate to create the DDL schema (hbm2ddl.auto = create) during current development (we will use static schema definition for later use). Hibernate automatically creates foreign keys for relationships, which is not bad for us.

If I instruct to use the same table mapping for joins (many-to-many, many-to-many, and one-to-one), it tries to create keys . And of course it is not possible to create a foreign key on RoleID

from Role_Group

to AdminRole

and DiscussantRole

at the same time, which is why I get an error.

Is there a way how to tell Hibernate

  • to create selected relationships without foreign keys

    or

  • to define that the relationship should be based on abstract ancestors (i.e. discussion group and its set should appear as 1: N - group and set)?

+1


source to share


2 answers


The following works for me as an answer to question number 2:

@ForeignKey( name = "none" )

      

No foreign key is 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, this is an undocumented feature that was seen in the 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 stated in Let Hibernate Connect Your World! (see page sources - xml config is not visible on page)

Note:

However, this does not solve the whole problem. Hibernate cannot get correct data through this mapping table for getAdmin

and getManagers

, since it looks like Role_Group

it finds RoleIDs

for DiscussionGroup

GroupID

and has no idea if it is for AdminRole

or ManagerRole

and gives "No row with given id exists" error ".

Mapping like this works, however, when I use a table like this in a Group or DiscussionGroup like public Set<Role> getRoles()

Hibernate will load the derived classes ( AdminRole

, ManagerRole

) in Set successfully .

+3


source


I think you should be storing multiple tables. It just displays the relationships that exist in your classes.



If you don't want that, you can define Set<Role>

within the abstract Group

and Set<Group>

within the abstract Role

. You would not have "subsets" in your subclasses; you simply populate the set from the abstract class with the appropriate elements of the correct type. The auto mapping will then give you one junction table as you want.

+1


source







All Articles