HomeAbout MeContact Me

Using Spring Data to persist a Set of Enums in a Many-To-Many relationship

By Emanuele Papa
Published in Development
August 24, 2017
1 min read
Using Spring Data to persist a Set of Enums in a Many-To-Many relationship

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

#development#java#jpa#spring#springdata#hibernate
Previous Article
MobaXterm - Enhanced SSH client for Windows
Emanuele Papa

Emanuele Papa

Android Developer

Topics

Android
AWS
Development
Linux
Info
Windows
Smart Home
Modding

Related Posts

Flutter Padding widgets generator with Paddinger
May 16, 2021
1 min
Copyright © Emanuele Papa 2021, All Rights Reserved.

Quick Links

HomeAbout MeContact MeRSS Feed

Social Media