JPA OneToMany Mapping Using Hibernate and MySQL

OneToMany as name suggest is the scenario where one entity can be linked to multiple entities.

For e.g. one BookShelf can contain multiple books. In this tutorial we will use the same problem statement and model it using JPA with Hibernate as the JPA implementation provider.

First we will write our simple BookShelf entity, BookShelf will contain a List of Books.

BookShelf.java

package com.mumz.jpa.mapping.onetomany;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * The Class BookShelf.
 * @author prabhat.jha
 */
@Entity
@Table(name = "BOOK_SHELF")
public class BookShelf {
	
	/** The id. */
	private Long	id		= null;

	/** The name. */
	private String	name	= null;
	
	/** The books. */
	private List<Book> books = null;

	/**
	 * Gets the id.
	 * 
	 * @return the id
	 */
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="BOOK_SHELF_ID")
	public Long getId() {
		return id;
	}

	/**
	 * Sets the id.
	 * 
	 * @param id
	 *            the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	@Column(name="BOOK_SHELF_NAME")
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 * 
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Gets the books.
	 * 
	 * @return the books
	 */
	@OneToMany(cascade=CascadeType.ALL, mappedBy="bookShelf")
	public List<Book> getBooks() {
		return books;
	}

	/**
	 * Sets the books.
	 * 
	 * @param books
	 *            the books to set
	 */
	public void setBooks(List<Book> books) {
		this.books = books;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the int
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((books == null) ? 0 : books.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @param obj
	 *            the obj
	 * @return true, if successful
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof BookShelf)) {
			return false;
		}
		BookShelf other = (BookShelf) obj;
		if (books == null) {
			if (other.books != null) {
				return false;
			}
		} else if (!books.equals(other.books)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		return true;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the string
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("BookShelf [id=%s, name=%s, books=%s]", id, name, books);
	}
}

On line number 78 we have added @OneToMany annotation with :

  1. cacade=CascadeType.ALL – Suggests what to do with Books when BookShelf is deleted
  2. mappedBy – Name of the owner object

Second we will write our Book entity which is a simple entity with @ManyToOne mapping.

Book.java

package com.mumz.jpa.mapping.onetomany;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * The Class Book.
 * @author prabhat.jha
 */
@Entity
@Table(name = "BOOK")
public class Book implements Serializable{
	
	/** The Constant serialVersionUID. */
	private static final long	serialVersionUID	= -4788522141255171404L;

	/** The id. */
	private Long		id			= null;

	/** The name. */
	private String		name		= null;

	/** The author. */
	private String		author		= null;

	/** The book shelf. */
	private BookShelf	bookShelf	= null;

	/**
	 * Gets the id.
	 * 
	 * @return the id
	 */
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="BOOK_ID")
	public Long getId() {
		return id;
	}

	/**
	 * Sets the id.
	 * 
	 * @param id
	 *            the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	@Column(name="BOOK_NAME")
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 * 
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Gets the author.
	 * 
	 * @return the author
	 */
	@Column(name="BOOK_AUTHOR")
	public String getAuthor() {
		return author;
	}

	/**
	 * Sets the author.
	 * 
	 * @param author
	 *            the author to set
	 */
	public void setAuthor(String author) {
		this.author = author;
	}

	/**
	 * Gets the book shelf.
	 * 
	 * @return the bookShelf
	 */
	@ManyToOne
	@JoinColumn(name="BOOK_SHELF_ID")
	public BookShelf getBookShelf() {
		return bookShelf;
	}

	/**
	 * Sets the book shelf.
	 * 
	 * @param bookShelf
	 *            the bookShelf to set
	 */
	public void setBookShelf(BookShelf bookShelf) {
		this.bookShelf = bookShelf;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the int
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((author == null) ? 0 : author.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @param obj
	 *            the obj
	 * @return true, if successful
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Book)) {
			return false;
		}
		Book other = (Book) obj;
		if (author == null) {
			if (other.author != null) {
				return false;
			}
		} else if (!author.equals(other.author)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		return true;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the string
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("Book [id=%s, name=%s, author=%s]", id, name, author);
	}
}

Third we will write a simple class to test out our application.

TestOneToMany


package com.mumz.jpa.mapping.onetomany;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

/**
 * The Class TestOneToMany.
 * @author prabhat.jha
 */
public class TestOneToMany {

	/**
	 * The main method.
	 * 
	 * @param args
	 *            the arguments
	 */
	public static void main(String[] args) {
		EntityManager entityManager = Persistence.createEntityManagerFactory("jpaPersistenceUnit").createEntityManager();

		BookShelf bookShelf = new BookShelf();
		bookShelf.setName("JPA Books");
		List<Book> books = new ArrayList<Book>();

		Book book = new Book();
		book.setName("Java Persistence with Hibernate");
		book.setAuthor("Christian Bauer and Gavin King");
		book.setBookShelf(bookShelf);

		books.add(book);

		book = new Book();
		book.setName("Hibernate Made Easy");
		book.setAuthor("Hibernate Made Easy");
		book.setBookShelf(bookShelf);

		books.add(book);

		bookShelf.setBooks(books);
		EntityTransaction entityTransaction = entityManager.getTransaction();
		try {
			entityTransaction.begin();
			entityManager.persist(bookShelf);
			entityTransaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
			entityTransaction.rollback();
		} finally {
			entityManager.close();
		}
	}
}

Fourth our persistence.xml which holds our mapped classes and database details.

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
	xmlns="http://java.sun.com/xml/ns/persistence" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation=
		"http://java.sun.com/xml/ns/persistence 
		http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
		
	<persistence-unit name="jpaPersistenceUnit"
		transaction-type="RESOURCE_LOCAL">
		<class>com.mumz.jpa.mapping.onetomany.BookShelf</class>
		<class>com.mumz.jpa.mapping.onetomany.Book</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa_schema" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password" value="root" />
		</properties>
	</persistence-unit>
</persistence>

Finally our pom.xml to maintain our dependency.

pom.xml

<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 
		http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mumz.test.jpa</groupId>
	<artifactId>TestJPAProject</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>TestJPAProject</name>
	<description>TestJPAProject</description>
	<dependencies>
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.0-api</artifactId>
			<version>1.0.0.Final</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Leave a comment