SpringBoot JPA @OneToMany Mapping as name says we will see one to many mapping in SpringBoot and JPA.
First see the ER Diagram
SpringBoot JPA @OneToMany Mapping ER Diagram
Following is the Entity Relationship Diagram for user, user_mails and user_mobiles table.
One user can have multiple mail ids.
So this is a one to many relation.
similarly one user can have multiple mobile numbers.
This is also one to many mapping.
user’s id in user table is

Tools/Technology used
- Spring Boot 2.2
- JPA
- Eclipse IDE
- MySQL Database
SpringBoot JPA @OneToMany Mapping Directory Structure

To build project we used maven and included
- spring-boot-starter-web
- spring-boot-starter-data-jpa
- mysql-connector-java
You can also use spring Initializr to generate POM.xml
POM.xml
4.0.0 org.springframework.boot spring-boot-starter-parent 2.7.2 com.ebhor mvc 0.0.1-SNAPSHOT war Spring Crud Spring CRUD Example 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-starter-test test mysql mysql-connector-java runtime org.springframework.boot spring-boot-maven-plugin
Application.properties file configuration
MySQL database is used.
Configuration with MySQL is as specified below
spring.datasource.url=jdbc:mysql://localhost:3306/ebhor spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
Entities
We have created three entity files User, UserMail and UserMobile.
Tables and columns are mapped in entity file.
User.java
To access multiple mail and mobile numbers user is mapped with UserMail and UserMobile entities.
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set userMails = new HashSet(0);
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set userMobiles = new HashSet(0);
@oneToMany mapping is used and few parameters are also used.
- mappedBy- a property name in userMails. Based on this property matching oneToMany mapping will be performed.
- cascade- Transactions that are performing on table will also perform on mapped table or not.
- fetch – specifies when to access mapped data from join table
package com.ebhor.crud.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
@Column(name = "name", nullable = false)
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set userMails = new HashSet(0);
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set userMobiles = new HashSet(0);
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getUserMails() {
return userMails;
}
public void setUserMails(Set userMails) {
this.userMails = userMails;
}
public User(int id, String name, Set userMails) {
super();
this.id = id;
this.name = name;
this.userMails = userMails;
}
public User() {
super();
}
public Set getUserMobiles() {
return userMobiles;
}
public void setUserMobiles(Set userMobiles) {
this.userMobiles = userMobiles;
}
}
UserMail.java
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
@JsonIgnore
private User user;
Here User Object is mapped as Many to one.
The @JoinColumn specified based on which (user_mail) column it will perform join and fetch data.
@JsonIgnore- This will ignored the json result and prevent the loop.
package com.ebhor.crud.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name = "user_mails")
public class UserMail {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "email", nullable = false)
private String email;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
@JsonIgnore
private User user;
public UserMail() {
super();
}
public UserMail(int id, String email, User user) {
super();
this.id = id;
this.email = email;
this.user = user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserMobiles
package com.ebhor.crud.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name = "user_mobiles")
public class UserMobile {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "mobile_no", nullable = false)
private String mobileNo;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id")
@JsonIgnore
private User user;
public UserMobile() {
}
public UserMobile(int id, String mobileNo, User user) {
super();
this.id = id;
this.mobileNo = mobileNo;
this.user = user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserDAO.java
UserDAO is responsible for fetching data from database.
package com.ebhor.crud.dao; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import com.ebhor.crud.entity.User; @Repository public interface UserDAO extends CrudRepository{ }
UserService.java
package com.ebhor.crud.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ebhor.crud.dao.UserDAO;
import com.ebhor.crud.entity.User;
@Service
public class UserService {
@Autowired
UserDAO dao;
public Iterable getUsers(){
return dao.findAll();
}
}
UserController.java
Here we have used RestController to show data on index position
package com.ebhor.crud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ebhor.crud.entity.User;
import com.ebhor.crud.service.UserService;
@RestController
public class UserController {
@Autowired
UserService service;
@GetMapping("/")
public Iterable users(){
return service.getUsers();
}
}
Result
On running above project we will get following data.

Read More