We will take the User and the Role entities to perform Many to Many unidirectional mapping.
The many-to-many relationship is implemented using a third table called the join table which contains foreign keys for each table.
Check out my Udemy course to Learn Spring Data JPA: Master Spring Data JPA with Hibernate
Many to Many Unidirectional Mapping - ER Diagram
1. Creating Spring Boot Project
Spring Boot provides a web tool called https://start.spring.io to bootstrap an application quickly. Just go to https://start.spring.io and generate a new spring boot project.Use the below details in the Spring boot creation:
Project Name: spring-data-jpa-course
Project Type: Maven
Choose dependencies: Spring Data JPA, MySQL Driver, Lombok
Package name: net.javaguides.springboot
Use the below details in the Spring boot creation:
Project Name: spring-data-jpa-course
Project Type: Maven
Choose dependencies: Spring Data JPA, MySQL Driver, Lombok
Package name: net.javaguides.springboot
2. Maven Dependencies
Here is the complete pom.xml for your reference:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.javaguides</groupId>
<artifactId>spring-data-jpa-course</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-jpa-course</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. Configure MySQL database
Let's use the MySQL database to store and retrieve the data in this example and we gonna use Hibernate properties to create and drop tables.
Open the application.properties file and add the following configuration to it:spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = create-drop
Make sure that you will create a demo database before running the Spring boot application.Also, change the MySQL username and password as per your MySQL installation on your machine.
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=Mysql@123
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto = create-drop
4. Create JPA Entities
Let's create an entity package inside a base package "net.javaguides.springboot".
User.java
package com.springdatajpa.springboot.entity;
import lombok.Getter;
import lombok.Setter;
import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Getter
@Setter
@Entity
@Table(
name = "users",
uniqueConstraints = @UniqueConstraint(
name = "unique_email",
columnNames = "email"
)
)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String firstName;
private String lastName;
private String email;
private String password;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
name = "users_roles",
joinColumns = @JoinColumn(
name = "user_id", referencedColumnName = "id"
),
inverseJoinColumns = @JoinColumn(
name = "role_id", referencedColumnName = "id"
)
)
private Set<Role> roles = new HashSet<>();
}
Role.java
package com.springdatajpa.springboot.entity;
import lombok.Getter;
import lombok.Setter;
import jakarta.persistence.*;
@Getter
@Setter
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
}
5. Create Spring Data JPA Repositories
Next, let's create Spring Data JPA repositories to access the User and Role entities from the database.
The JpaRepository interface defines methods for all the CRUD operations on the entity, and a default implementation of the JpaRepository called SimpleJpaRepository.
Let's create a repository package inside a base package "net.javaguides.springdatarest".
Within the repository package, create UserRepository and RoleRepository interfaces with the following content:
Next, let's create Spring Data JPA repositories to access the User and Role entities from the database.
The JpaRepository interface defines methods for all the CRUD operations on the entity, and a default implementation of the JpaRepository called SimpleJpaRepository.
UserRepository.java
package com.springdatajpa.springboot.repository;
import com.springdatajpa.springboot.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
RoleRepository.java
package com.springdatajpa.springboot.repository;
import com.springdatajpa.springboot.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Long> {
}
6. Testing Many to Many Unidirectional Mapping
Let's write the JUnit test to perform CRUD operations on many-to-many unidirectional mapping using Spring Data JPA:
package com.springdatajpa.springboot.repository;
import com.springdatajpa.springboot.entity.Role;
import com.springdatajpa.springboot.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ManyToManyUnidirectionalTest {
@Autowired
private UserRepository userRepository;
@Test
void saveUser(){
User user = new User();
user.setFirstName("ramesh");
user.setLastName("fadatare");
user.setEmail("ramesh@gmail.com");
user.setPassword("secrete");
Role admin = new Role();
admin.setName("ROLE_ADMIN");
Role customer = new Role();
customer.setName("ROLE_CUSTOMER");
user.getRoles().add(admin);
user.getRoles().add(customer);
userRepository.save(user);
}
@Test
void updateUser(){
User user = userRepository.findById(1L).get();
user.setFirstName("ram");
user.setEmail("ram@gmail.com");
Role roleUser = new Role();
roleUser.setName("ROLE_USER");
user.getRoles().add(roleUser);
userRepository.save(user);
}
@Test
void fetchUser(){
User user = userRepository.findById(1L).get();
System.out.println(user.getEmail());
user.getRoles().forEach((r) -> {
System.out.println(r.getName());
});
}
@Test
void deleteUser(){
userRepository.deleteById(1L);
}
}
Save User will also save associated roles:
@Test
void saveUser(){
User user = new User();
user.setFirstName("ramesh");
user.setLastName("fadatare");
user.setEmail("ramesh@gmail.com");
user.setPassword("secrete");
Role admin = new Role();
admin.setName("ROLE_ADMIN");
Role customer = new Role();
customer.setName("ROLE_CUSTOMER");
user.getRoles().add(admin);
user.getRoles().add(customer);
userRepository.save(user);
}
Update User will also update associated roles:
@Test
void updateUser(){
User user = userRepository.findById(1L).get();
user.setFirstName("ram");
user.setEmail("ram@gmail.com");
Role roleUser = new Role();
roleUser.setName("ROLE_USER");
user.getRoles().add(roleUser);
userRepository.save(user);
}
Fetch User will also fetch its associated roles:
@Test
void fetchUser(){
User user = userRepository.findById(1L).get();
System.out.println(user.getEmail());
user.getRoles().forEach((r) -> {
System.out.println(r.getName());
});
}
Delete User will also delete its associated roles:
@Test
void deleteUser(){
userRepository.deleteById(1L);
}
Comments
Post a Comment
Leave Comment