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!


Emanuele Papa
Copyright © Emanuele Papa 2025, All Rights Reserved.
Our website uses cookies to analyze how the site is used and to ensure your experience is consistent between visits. Read our Cookies Policy

Social Media