Java Persistence API is a standard specification. It provides a persistence model that’s implemented by different numerous of implementer.
Hibernate & EclipseLink are two most popular implementations used for persisting given business model against some sort of persistence store like relational database. As such, this tutorial will provide you a full-fledged example containing all required configuration steps to developer a layered application that uses:
We’ve discussed before using of Hibernate ORM for persisting given domain classes in a multiple tutorials but today we will use only JPA based configurations. JPA specification does its bootstrap in a different way. In hibernate we’ve bootstrapped our application by using hibernate.cfg.xml file, but JPA doesn’t specify such that file. As such, JPA provides another way of configuration, it’s using of persistence.xml file which located within your classpath and under META-INF folder. Let’s see how can we use both of Hibernate andEclipseLink for implementing a single registration form.
Before proceeding far away, you must prepare your environments that should contain for:
We have Employee table in our MySQL database, you can use below script to create it.
CREATE TABLE `employee` ( `EMP_ID` int(11) NOT NULL AUTO_INCREMENT, `EMP_NAME` varchar(45) DEFAULT NULL, `EMP_HIRE_DATE` datetime DEFAULT NULL, `EMP_SALARY` decimal(11,4) DEFAULT NULL, PRIMARY KEY (`EMP_ID`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
We have also one domain class that would be persisting into our database Employee table.
package com.journaldev.hibernate.jpa.data; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; @Entity public class Employee { @Id @Column(name="EMP_ID") private long employeeId; @Column(name="EMP_NAME") private String employeeName; @Column(name="EMP_HIRE_DATE") @Temporal(TemporalType.TIMESTAMP) private Date employeeHireDate; @Column(name="EMP_SALARY") private double employeeSalary; public long getEmployeeId() { return employeeId; } public void setEmployeeId(long employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public Date getEmployeeHireDate() { return employeeHireDate; } public void setEmployeeHireDate(Date employeeHireDate) { this.employeeHireDate = employeeHireDate; } public double getEmployeeSalary() { return employeeSalary; } public void setEmployeeSalary(double employeeSalary) { this.employeeSalary = employeeSalary; } }
As we’ve mentioned earlier, JPA provides an alternative way for bootstrapping JPA framework, it’s apersistence.xml file. The minimum amount of this file should look like:
<persistence 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" version="2.0"> <!-- Will be referenced in Spring Context File --> <persistence-unit name="jpa-persistence" transaction-type="RESOURCE_LOCAL"> <class>com.journaldev.hibernate.jpa.data.Employee</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/journaldev" /> <property name="javax.persistence.jdbc.user" value="pankaj" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.password" value="pankaj123" /> </properties> </persistence-unit> </persistence>
Persistence unit should define:
All required libraries are listed within pom.xml file that’s read by Maven itself.
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.journaldev</groupId> <artifactId>Primefaces-Hibernate-JPA-Spring-Integration-Sample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Primefaces-Hibernate-JPA-Spring-Integration-Sample Maven Webapp</name> <url>http://maven.apache.org</url> <repositories> <repository> <id>prime-repo</id> <name>PrimeFaces Maven Repository</name> <url>http://repository.primefaces.org</url> <layout>default</layout> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- Faces Implementation --> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>2.2.4</version> </dependency> <!-- Faces Library --> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.2.4</version> </dependency> <!-- Primefaces Version 5 --> <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>5.0</version> </dependency> <!-- JSP Library --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> </dependency> <!-- JSTL Library --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> </dependency> <!-- Hibernate 4.3.6 core library library --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.6.Final</version> </dependency> <!-- Hibernate 4.3.6 JPA support --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.6.Final</version> </dependency> <!-- MySQL driver connector library --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.31</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.0.3.RELEASE</version> </dependency> <!-- Spring Web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.3.RELEASE</version> </dependency> <!-- Dependencies for Eclipse JPA Persistence API --> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.5.0-RC1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> </project>
Persisting using of JPA requires an instance of EntityManager. This instance can be acquired by configuring a proper Spring context.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- Enable Spring Annotation Configuration --> <context:annotation-config /> <!-- Scan for all of Spring components such as Spring Service --> <context:component-scan base-package="com.journaldev.spring.service"></context:component-scan> <!-- Necessary to get the entity manager injected into the factory bean --> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <!-- Define Hibernate JPA Vendor Adapter --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /> </bean> <!-- Entity Manager Factory --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="hibernate.jpa"></property> <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> </bean> <!-- Transaction Manager --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- Detect @Transactional --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
Same configuration would be used for EclipseLink, a small change is required is to provide EclipseLink’s JPA vendor. Just change the jpaVendorAdapter bean to below and the JPA implementation used will be EclipseLink.
<!-- Define EclipseLink JPA Vendor Adapter --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> <property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform" /> <property name="generateDdl" value="false" /> <property name="showSql" value="true" /> </bean>
Proper configuration of Spring requires adding of Spring listener into Primefaces’ deployment descriptorweb.xml application.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5" metadata-complete="true"> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <context-param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> </web-app>
Spring service is the interaction point between presentation layer and persistence layer. If you’re familiar with DAO, you can consider it something similar.
package com.journaldev.spring.service; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.journaldev.hibernate.jpa.data.Employee; @Component public class EmployeeService { @PersistenceContext private EntityManager em; public EntityManager getEm() { return em; } public void setEm(EntityManager em) { this.em = em; } @Transactional public void register(Employee emp) { // Save employee this.em.persist(emp); } }
RegisterEmployee is a faces managed bean that’s used for handling user interaction and validation of user’s input.
package com.journaldev.prime.faces.beans; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; import com.journaldev.jpa.data.Employee; import com.journaldev.spring.service.EmployeeService; @ManagedBean @SessionScoped public class RegisterEmployee { @ManagedProperty("#{employeeService}") private EmployeeService employeeService; private Employee employee = new Employee(); public EmployeeService getEmployeeService() { return employeeService; } public void setEmployeeService(EmployeeService employeeService) { this.employeeService = employeeService; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public String register() { // Calling Business Service employeeService.register(employee); // Add message FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("The Employee "+this.employee.getEmployeeName()+" Is Registered Successfully")); return ""; } }
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> <h:head> <script name="jquery/jquery.js" library="primefaces"></script> <title>Register Employee</title> </h:head> <h:form> <p:growl id="messages"></p:growl> <p:panelGrid columns="2"> <p:outputLabel value="Enter Employee Name:"></p:outputLabel> <p:inputText value="#{registerEmployee.employee.employeeName}"></p:inputText> <p:outputLabel value="Enter Employee Hire Date:"></p:outputLabel> <p:calendar value="#{registerEmployee.employee.employeeHireDate}"></p:calendar> <p:outputLabel value="Enter Employee Salary:"></p:outputLabel> <p:inputText value="#{registerEmployee.employee.employeeSalary}"></p:inputText> </p:panelGrid> <p:commandButton value="Register" action="#{registerEmployee.register}" update="messages"></p:commandButton> </h:form> </html>
This tutorial aimed to help you get both of Hibernate and EclipseLink JPA implementations used into your project. JPA has changed your life, it’s so easy to configure, use and track. It’s plugged in with a default logging mechanism that would help you find your problem shortly. Contribute us by commenting below and find downloaded source code.