Home > AI > Backend > SpringBoot > mysql-connector-java >

@ManyToMany

Method 1: Join Table

 In a join table, the combination of the foreign keys will be its composite primary key.

Example 1: User and Role

User.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "test_users")
public class User implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    private int id;


    @Column(name = "username")
    @Length(min = 5, message = "*Your user name must have at least 5 characters")
    @NotEmpty(message = "*Please provide a user name")
    private String username;


    @Column(name = "email")
    @Email(message = "*Please provide a valid Email")
    @NotEmpty(message = "*Please provide an email")
    private String email;


    @Column(name = "password")
    @Length(min = 5, message = "*Your password must have at least 5 characters")
    @NotEmpty(message = "*Please provide your password")
    private String password;

    @Column(name = "firstName")
    @NotEmpty(message = "*Please provide your name")
    private String firstName;


    @Column(name = "lastName")
    @NotEmpty(message = "*Please provide your last name")
    private String lastName;


    @Column(name = "active")
    private Boolean active = true;


    @ManyToMany(cascade = CascadeType.MERGE)
    @JoinTable(
            name = "test_users_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles;







    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();

        for (Role r : roles) {
            authorities.add(new SimpleGrantedAuthority(r.getName()));
        }

        return authorities;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

Role.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "test_roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "role_id")
    private int id;

    @Column(name = "name")
    private String name;
    
}

Then, we would have 3 tables, test_users, test_roles

test_users
test_roles
test_users_rolesrole_id,
user_id

Example 2: Student likes courses

Use @ManyToMany only on both tables

@Entity
class Student {

    @Id
    Long id;

    @ManyToMany
    Set<Course> likedCourses;

    // additional properties
    // standard constructors, getters, and setters
}

@Entity
class Course {

    @Id
    Long id;

    @ManyToMany
    Set<Student> likes;

  
}

More concise version

@Entity
class Student {

    @Id
    Long id;

    @ManyToMany
    @JoinTable(
            name = "students_like_courses",
            joinColumns = @JoinColumn(name = "student_id"),
            inverseJoinColumns = @JoinColumn(name = "course_id"))
    Set<Course> likedCourses;

}

@Entity
class Course {

    @Id
    Long id;

    @ManyToMany(mappedBy = "likedCourses")
    Set<Student> likes;

}

Example 3, the relationship itself has an attribute.

@Entity
class Student {

    @Id
    Long id;


    @OneToMany(mappedBy = "course")
    Set<CourseRating> ratings;

}

@Entity
class Course {

    @Id
    Long id;


    @OneToMany(mappedBy = "course")
    Set<CourseRating> ratings;

}


@Embeddable
class CourseRatingKey implements Serializable {

    @Column(name = "student_id")
    Long studentId;

    @Column(name = "course_id")
    Long courseId;
}



@Entity
class CourseRating {

    @EmbeddedId
    CourseRatingKey id;

    @ManyToOne
    @MapsId("studentId")
    @JoinColumn(name = "student_id")
    Student student;

    @ManyToOne
    @MapsId("courseId")
    @JoinColumn(name = "course_id")
    Course course;

    int rating;

}


Since it’s an entity, it’ll have its own primary key.

@Entity
class Student {

    @Id
    Long id;


    @OneToMany(mappedBy = "student")
    Set<CourseRegistration> registrations;

}

@Entity
class Course {

    @Id
    Long id;


    @OneToMany(mappedBy = "course")
    Set<CourseRegistration> registrations;

}





@Entity
class CourseRegistration {

    @Id
    Long id;

    @ManyToOne
    @JoinColumn(name = "student_id")
    Student student;

    @ManyToOne
    @JoinColumn(name = "course_id")
    Course course;

    LocalDateTime registeredAt;

    int grade;

}

Leave a Reply