Hibernate 4 One to Many mapping annotation example with Struts2

In this tutorial, we are going to see that how to implement Hibernate One to Many Mapping using Annotations (Java Persistence API (JPA)) with Struts 2 support. Let us start with an example for creating sample web page for adding multiple recipients for a single message to be sent for all recipients (One to Many). The message can be sent to many recipients (i.e. Many recipients will receive the same message).

Let us design tables for Message & Recipient  which has one to many relationship ( Recipient table will have the foreign key (message_id) which points to the primary key of Message table)

one to  many mapping err diagram

Message Table:


Field | Type | Null | Key | Default | Extra |
------------+--------------+------+-----+---------+-------+
message_id | varchar(255) | NO | PRI | NULL | |
createdOn | date | YES | | NULL | |
message | varchar(255) | YES | | NULL | |
CREATE TABLE <code>message</code> (
<code>message_id</code> varchar(255) NOT NULL,
<code>createdOn</code> date DEFAULT NULL,
<code>message</code> varchar(255) DEFAULT NULL,
PRIMARY KEY (<code>message_id</code>)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Recipient Table:


+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| recipient_id | varchar(255) | NO | PRI | NULL | |
| email | varchar(255) | YES | | NULL | |
| recipient_name | varchar(255) | YES | | NULL | |
| sno | bigint(20) | YES | | NULL | |
| message_id | varchar(255) | YES | MUL | NULL | |
+----------------+--------------+------+-----+---------+-------+

CREATE TABLE <code>recipient</code> (
<code>recipient_id</code> varchar(255) NOT NULL,
<code>email</code> varchar(255) DEFAULT NULL,
<code>recipient_name</code> varchar(255) DEFAULT NULL,
<code>sno</code> bigint(20) DEFAULT NULL,
<code>message_id</code> varchar(255) DEFAULT NULL,
PRIMARY KEY (<code>recipient_id</code>),
KEY <code>FK_mqajlj3949jux1jd609pmhfvx</code> (<code>message_id</code>),
CONSTRAINT <code>FK_mqajlj3949jux1jd609pmhfvx</code> FOREIGN KEY (<code>message_id</code>) REFERENCES <code>message</code> (<code>message_id</code>)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Now let us create two model classes called Message and Recipient for mapping the above tables.

Message.java


package net.javaonline.dto;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
import java.util.List;

@Entity
@Table(name="message")
public class Message implements Serializable{

@Id
@Column(name="message_id")
private String message_id;
private String message;

@Temporal(TemporalType.DATE)
@Column (name="createdOn")
private Date createdOn;

// One to Many mapping using List
@OneToMany(mappedBy="message", cascade = CascadeType.ALL)
private List<Recipient> recipients;
public String getMessage_id() {
return message_id;
}
public void setMessage_id(String message_id) {
this.message_id = message_id;
}

@Column(name="message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<Recipient> getRecipients() {
return recipients;
}
public void setRecipients(List<Recipient> recipients) {
this.recipients = recipients;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}

}

Recipient.java


package net.javaonline.dto;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="Recipient")
public class Recipient implements Serializable{

private Long sno;

@Id
@Column(name="recipient_id")
private String recipient_id;
private String recipient_name;
private String email;

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="message_id") //message_id as foreign key
private Message message; //reference table message

public String getRecipient_id() {
return recipient_id;
}
public void setRecipient_id(String recipient_id) {
this.recipient_id = recipient_id;
}

@Column(name="recipient_name")
public String getRecipient_name() {
return recipient_name;
}
public void setRecipient_name(String recipient_name) {
this.recipient_name = recipient_name;
}

public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}

public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}

@Column(name="sno")
public Long getSno() {
return sno;
}
public void setSno(Long sno) {
this.sno = sno;
}

}

Project Structure

project structure one to many
Jars required

Additional Jars

Action Class

package net.javaonline.controller;

import java.util.List;

import net.javaonline.dto.Message;
import net.javaonline.dto.Recipient;

import com.opensymphony.xwork2.ActionSupport;

public class MessageManager extends ActionSupport{

private Message message;
private List <Recipient> recipientList;
private MessageManagerDAO messageDao;
private int rowindex;

public int getRowindex() {
return rowindex;
}

public void setRowindex(int rowindex) {
this.rowindex = rowindex;
}

public MessageManager() {
messageDao = new MessageManagerDAO();
}
public List<Recipient> getRecipientList() {
return recipientList;
}

public void setRecipientList(List<Recipient> recipientList) {
this.recipientList = recipientList;
}
public Message getMessage() {
return message;
}

public void setMessage(Message message) {
this.message = message;
}
public String add() {
System.out.println(getMessage());
try {
message=getMessage();
System.out.println("Message code " + message.getMessage_id());
message.setCreatedOn(new java.util.Date()); // for current date to store on createdOn field.
recipientList=message.getRecipients();

//For storing message id for each recipient

for (Recipient recipient : recipientList) {
System.out.println("Recipient Sno= "+ recipient.getSno());
System.out.println("Recipient Code= "+ recipient.getRecipient_id());
System.out.println("Recipient Name= "+ recipient.getRecipient_name());
System.out.println("Recipient Price= "+ recipient.getEmail());
recipient.setMessage(message);
}

messageDao.add(message);

} catch (Exception e) {
e.printStackTrace();
}

return SUCCESS;
}

}

DAO File:  For saving Message object in message table. List of Recipient Objects are saved automatically in recipient table because of One to Many Mapping

package net.javaonline.controller;

import util.HibernateUtil;
import net.javaonline.dto.Message;
import org.hibernate.Session;

public class MessageManagerDAO extends HibernateUtil {

public Message add(Message message) {
Session session = HibernateUtil.createSessionFactory().getCurrentSession();
session.beginTransaction();
session.saveOrUpdate(message);
session.getTransaction().commit();
return message;
}

} 

HibernateUtil.java //for creating hibernate session

package util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;

public static SessionFactory createSessionFactory() {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}

} 

Hibernate Configuration File:

Mention the below mapping in hibernate.cfg.xml

<mapping class=”net.javaonline.dto.Message” />
<mapping class=”net.javaonline.dto.Recipient” />
Complete hibernate.cfg.xml


<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/test
</property>
<property name="connection.username">root</property>
<property name="connection.password">******</property>

<property name="connection.pool_size">1</property>

<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->
<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>

<!-- Display all generated SQL to stdout -->
<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>

<mapping class="net.javaonline.dto.Message" />
<mapping class="net.javaonline.dto.Recipient" />

</session-factory>

</hibernate-configuration> 

struts.xml file


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />

<package name="default" extends="struts-default" namespace="/">

<action name="add"
class="net.javaonline.controller.MessageManager" method="add">
<result name="input">/MessageRecipientAdd.jsp</result>
<result name="success">/Ack.jsp</result>
</action>

</package>

</struts> 

MessageRecipientAdd.jsp

The below JSP file, dynamically generates row for adding multiple recipients which is mapped to list of Recipient objects.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Message / Recipient Add / Modify Details - Struts2 Hibernate 4 </title>

<script type ="text/javascript">

function addMoreRecipients(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);

var cell1 = row.insertCell(0);
var snoCol = document.createElement("input");
snoCol.type = "text";
snoCol.name="message.recipients["+(rowCount-1)+"].sno";
snoCol.value=rowCount;
cell1.appendChild(snoCol);

var cell2 = row.insertCell(1);
var idCol = document.createElement("input");
idCol.type = "text";
idCol.name="message.recipients["+(rowCount-1)+"].recipient_id";
cell2.appendChild(idCol);

var cell3 = row.insertCell(2);
var nameCol = document.createElement("input");
nameCol.type = "text";
nameCol.name="message.recipients["+(rowCount-1)+"].recipient_name";
cell3.appendChild(nameCol);

var cell4 = row.insertCell(3);
var emailCol = document.createElement("input");
emailCol.type = "text";
emailCol.name="message.recipients["+(rowCount-1)+"].email";
cell4.appendChild(emailCol);
return false;

}

</script>

</head>
<body>

<h3>Message Recipient Details</h3>
<s:actionerror/>

<s:form name="messageForm" action="add" method="post" theme="%{currentTheme}">
<s:hidden name="rowindex"/>

<TABLE id="ticketTable" width="350px" border="1">
<TR>
<td>
Message Id : <s:textfield name="message.message_id" label="message id"/>
</td>
<td>
Message : <s:textarea name="message.message" cols="50" rows ="3" label="Message"/>
</td>
</TR>

</TABLE>

Add / Remove Recipient Details :
<TABLE id="pdTable" border="1">
<TR>
<TD>S.No.</TD>
<TD>Recipient Id</TD>
<TD>Recipient Name</TD>
<TD>Email</TD>
</TR>

<s:iterator value="message.recipients" status="cnt" var="recipientList">
<tr>
<TD> <s:textfield name="message.recipients[%{#cnt.count-1}].sno" /> </TD>
<TD> <s:textfield name="message.recipients[%{#cnt.count-1}].recipient_id" /> </TD>
<TD> <s:textfield name="message.recipients[%{#cnt.count-1}].recipient_name" /> </TD>
<TD> <s:textfield name="message.recipients[%{#cnt.count-1}].email" /> </TD>
</tr>
</s:iterator>

</TABLE>
<table>
<tr>
<td align="right">
<input type="button" value="Add More Recipients" onclick="addMoreRecipients('pdTable')"/>
</td>
</tr>
</table>

<table>
<tr>
<td align="center">
<s:submit value="Submit" align="center"/>
</td>

</tr>
</table>

</s:form>

</body>
</html> 

Ack.jsp //For acknowledgement

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Message Recipient Ack</title>
</head>
<body>
<h2>Message Recipient Ack</h2>
<div align="left">Your Below Message will be sent to the following recipients.</div>
<table border="1">
<tr>
<td colspan=2>Message Id : <s:property value="message.message_id"/></td>
<td colspan=2>Message : <s:property value="message.message"/></td>
</tr>

<tr>
<td colspan=4 align="center">
<h5>Recipient Details</h5>
</td>
</tr>

<TR>
<TD>S.No.</TD>
<TD>Recipient Id</TD>
<TD>Recipient Name</TD>
<TD>Email</TD>
</TR>

<s:iterator value="message.recipients" var="recipients">
<tr>
<td><s:property value="sno"/></td>
<td><s:property value="recipient_id"/></td>
<td><s:property value="recipient_name"/></td>
<td><s:property value="email"/></td>
</tr>
</s:iterator>
</table>
</body>
</html> 

Run the above application using the below URL, fill the form and submit

http://localhost:8080/Struts2Hibernate1toMany/

One to many mapping Message

ack

Both Tables (Message & Recipient)  Output:

table output

Reference :

Hibernate Association Mappings

 

You may also like

Leave a Reply

Be the First to Comment!