Blessed
Blessed

Reputation: 13

Mapping 3 entities through a common bridge table using Hibernate

I want to model the fact that a team needs multiple skills to function. Many persons can have a certain skill. A person has many skills. A person can be part of many teams.

I use Hibernate to model this scenario. I started building with two entities, team and skill, and used @ManyToMany annotation to link these dependencies. Trying to add the third entity, person, is where it got difficult. I don't understand how I should build this model and would greatly appreciate any help.

I don't have much experience using Hibernate so this is a challenge.

I have searched for information and most examples I found was about two connected entities and I haven't been able to scale those examples to include a third entity.

These are my entities:

package com.example.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.Set;

@Entity
public class Team {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToMany
    private Set<Skill> skills;

    @ManyToMany
    private Set<Person> persons;
}



package com.example.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import java.util.Set;

@Entity
public class Skill {
    @Id
    @GeneratedValue
    private Long id;

    private String knowHow;

    @ManyToMany
    private Set<Team> teams;

    @ManyToMany
    private Set<Person> persons;
}



package com.example.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.util.Set;

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private Set<Team> teams;
    private Set<Skill> skills;
}

These are my repositories:

package com.example.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.entity.Competence;
import com.example.entity.Team;

import java.util.List;

@Repository
public interface TeamRepository extends CrudRepository<Team, Long> {
    List<Competence> findDistinctByKnowHow(String name);
}



package com.example.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.entity.Competence;
import com.example.entity.Skill;

import java.util.List;

@Repository
public interface SkillRepository extends CrudRepository<Skill, Long> {

    List<Competence> findDistinctByKnowHow(String knowHow);

}



package com.example.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.example.entity.Competence;
import com.example.entity.Person;

import java.util.List;

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {

    List<Competence> findDistinctByPerson(String name);

}

Upvotes: 1

Views: 675

Answers (3)

Taher Stenberg
Taher Stenberg

Reputation: 148

One way to solve this is to create an entity that solely exists as a bridge entity. That way you can add three different 1-to-many relationsships between your "real" entities and your bridge entity. That way you should be able to handle the threeway many-to-many relationship.

You will probably have to handle the data in the bridge entity "manually" though.

Upvotes: 1

Taher Stenberg
Taher Stenberg

Reputation: 148

I think that the question has merit.

Using a common bridge table between the three entities allows for a row level security by design assuming a team can only see the competencies they add themselves.

Take the example of a consultant working with VB in one team. She truly dislikes VB and does not want her other team to know that she has this skill.

Team A can know Person A has the Skill VB. Team B should not know that Person A has the Skill VB.

I would have added this as a comment but I lack the necessary reputation =/

Upvotes: 0

pantuptus
pantuptus

Reputation: 183

I am afraid you are not able to do that. This model contains logical inconsistency and can lead to contradictions. Imagine that you have a TeamA which contains 2 members (PersonA, PersonB). PersonA contains SkillA and PersonB contains SkillB. That means that TeamA should contain 2 skills (SkillA and SkillB). However, your model should allow for putting skills on team level independently of members. What would happen then if you'd put only SkillA on skills property of TeamA?

I think you should leave many-to-many relationship between

  • Person and Skill
  • Team and Person

The skills property on Team level should be derived.

Upvotes: 0

Related Questions