Spring Data One To Many Mapping

One-To-Many relationship is used widely in database operations. For exampel a user can have multiple cars or a user can have multiple computer screens to work with.

Our example is a user can have multiple orders as in a restaurant order. Let’s suppose you are asked to develop a pizza restaurant application where customers can order online. a User can have multiple orders.

One-To-Many Bidirectional Relationship

// On the parent side which is the User class.
@OneToMany(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Set<Order> orders;
// On the child side which is the Order class.
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", nullable=false)
private User user;
package com.lovemesomecoding.user;

import java.io.Serializable;
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.OneToOne;
import javax.persistence.Table;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.lovemesomecoding.order.Order;

@JsonInclude(value = Include.NON_NULL)
@Entity
@Table(name = "user")
public class User implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id", nullable = false, updatable = false, unique = true)
	private Long id;
	
	@Column(name = "uid", unique = true, nullable=false, updatable=false)
	private String uid;

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

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

	@Column(name = "age")
	private int age;
	
	
	@JsonIgnoreProperties(value= {"user"})
	@OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	private Set<Order> orders;

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	// getters and setters
	
	public void addOrder(Order order) {
		if(this.orders == null){
			this.orders = new HashSet<>();
		}
		this.orders.add(order);
	}

}
package com.lovemesomecoding.order;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;

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 javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hibernate.annotations.CreationTimestamp;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.lovemesomecoding.user.User;

@JsonInclude(value = Include.NON_NULL)
@Entity
@Table(name = "user_order")
public class Order implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id", nullable = false, updatable = false, unique = true)
	private Long id;
	
	@Column(name = "uid", unique = true, nullable=false, updatable=false)
	private String uid;
	
	@Column(name = "coupon_code")
	private String couponCode;
	
	@Column(name = "discount")
	private Double discount;
	
	@Column(name = "total_amount")
	private Double totalAmount;
	
	@Column(name = "payment_method_id")
	private Long paymentMethodId;
	
	@CreationTimestamp
	@Column(name = "created_at")
	private Date createdAt;
	
	@JsonIgnoreProperties(value= {"orders"})
	@ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id", nullable=false)
	private User user;

	public Order() {
		super();
		// TODO Auto-generated constructor stub
	}
        // setters and getters
}

One-To-Many Unidirectional Relationship
It depends on the needs you might have. If you need to access orders from the User class then you use this below:

// On the parent side(User class)
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Order> orders;

or if you need to access a user from the Order class then your use this below:

// On the child side(Order class)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", nullable=false)
private User user;

My preference and what I recommend is to use bidirectional. Using unidirectional will slow down your system as it creates an extra join for the associative table that references the child table to the parent table.

Use mappedBy on the @OneToMany otherwise, it will create a reference or associative table.

@JoinColumn is always on the owing side or the child side of the relationship.

Source Code Github




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *