HomeAbout MeContact Me
Using Spring Data to persist a Set of Enums in a Many-To-Many relationship
Development
Using Spring Data to persist a Set of Enums in a Many-To-Many relationship
Emanuele Papa
Emanuele Papa
August 24, 2017
1 min

Usually, when we write a Many-To-Many relationship it is between 2 entities. Sometimes, it could happen that we have an entity which has a field which is a set of enum. In this case, we need to approach the problem differently and Spring comes to help.

Let’s see an example where we have two classes: Person and Skill (e.g. swimming, running, etc).

Many-To-Many between entities example

The following code shows what the situation is when Person and Skill are both entities.

@Entity 
public class Person {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
  private Long id;

  private String name;

  @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "person_skill", joinColumns = {
    @JoinColumn(name = "person_id")
  }, inverseJoinColumns = {
    @JoinColumn(name = "skill_id")
  }) 
  private Set <Skill> skillSet;
}

@Entity 
public class Skill {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
  private Long id;
  private String name;
}

To use this mapping, you would have 3 tables. You can create them with the following SQL code.

CREATE TABLE `person` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT, 
  `name` VARCHAR(45) NOT NULL, 
  PRIMARY KEY (`id`)
);

CREATE TABLE `skill` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT, 
  `name` VARCHAR(45) NOT NULL, 
  PRIMARY KEY (`id`)
);

CREATE TABLE `person_skill` (
  `person_id` BIGINT(20) NOT NULL, 
  `skill_id` BIGINT(20) NOT NULL, 
  PRIMARY KEY (`person_id`, `skill_id`), 
  INDEX `skill_fk_idx` (`skill_id` ASC), 
  CONSTRAINT `person_fk` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
  CONSTRAINT `skill_fk` FOREIGN KEY (`skill_id`) REFERENCES `skill` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);

Many-To-Many between entity and enum example

The following code shows what the situation is when Person is an entity and Skill is an enum.

@Entity 
public class Person {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
  private Long id;

  private String name;

  @ElementCollection(targetClass = Skill.class) 
  @CollectionTable(name = "person_skill", joinColumns = @JoinColumn(name = "person_id")) 
  @Enumerated(EnumType.STRING) 
  @Column(name = "skill_name") 
  private Set <Skill> skillSet;
}

public enum Skill {
  RUNNING,
  SWIMMING
}

To use this mapping, you would have only 2 tables, because Skill is not an entity and would not have its own table. You can create them with the following SQL code.

CREATE TABLE `person` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT, 
  `name` VARCHAR(45) NOT NULL, 
  PRIMARY KEY (`id`)
);

CREATE TABLE `person_skill` (
  `person_id` BIGINT(20) NOT NULL, 
  `skill_name` VARCHAR(45) NOT NULL, 
  PRIMARY KEY (`person_id`, `skill_name`), 
  CONSTRAINT `person_fk` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);

As you can see here, you don’t have the table skill because Skill is not an entity but only an enum; you only have to create the table which represents the relationship between Person and Skill.

Furthermore, since we added the annotation @Enumerated(EnumType.STRING), Spring Data will save the name of the entity in the database (look, we put a VARCHAR column). If you prefer, you could use EnumType.ORDINAL and Spring Data will save the ordinal value of the entity (1,2,3,etc..), so change the column to accept a numeric value.

That’s it!


Tags

Previous Article
MobaXterm - Enhanced SSH client for Windows
Emanuele Papa

Emanuele Papa

Android Developer

Related Posts

Flutter Padding widgets generator with Paddinger
Flutter Padding widgets generator with Paddinger
May 16, 2021
1 min

Quick Links

HomeAbout MeContact MeRSS Feed

Social Media