Almost every Java developer knows that Hibernate is widely used via it's native approach, but have you ever tried it
using via standard JPA (Java Persistence API) approach? Once I have faced an issue in terms of migrating from
OpenJPA to Hibernate, but I had to use Hibernate as JPA implementation. The whole internet is full of examples how
Hibernate is used via it's native approach, it took me sometime to get it working over JPA also using Spring. This blog contains detailed
information how Hibernate can be configured and used via JPA. The benefit of using Hibernate as the implementation of JPA is that if you would want to change the persistence implementation it would be straightforward - you just need to make sure you are not using any framework specific things. It has to be pure JPA and framework - just an implementation.
Technologies used:
- Spring 3.2.3.RELEASE
- Hibernate 4.2.2.Final
- JPA 2.0
- MySQL
- Tomcat 7
- Maven 3.0.5
- JDK 1.7
Lets start with reviewing the whole project's structure:
This project contains Spring controller, Spring model attribute, JPA entity, facade to perform JPA EntityManager's
operations, Hibernate SQL Schema generator, persistence configuration file, project configuration properties, Spring
dispatcher and application context configuration files, deployment descriptor, view page and Maven build file. Before
going in details make sure that you have created project structure like shown in this image. We will go through all of
these in details in a moment.
- Creating Maven build script
In the project root folder create a file named
pom.xml
which will be used to build the whole project into web application archive -
.war file, which later in this case will be
deployed into
Tomcat 7 servlet container.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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.paulius.hibernateviajpa</groupId>
<artifactId>hibernateviajpa</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>${war.symbolicName} [${war.namespace}]</name>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF8</project.build.sourceEncoding>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
<war.symbolicName>Hibernate Via JPA</war.symbolicName>
<war.namespace>com.paulius.hibernateviajpa</war.namespace>
<org.springframework.version>3.2.3.RELEASE</org.springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.2.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.2.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.19</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>HibernateViaJPA##${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<archive>
<manifestEntries>
<Build-Location>${basedir}</Build-Location>
<Build-Machine>${env.COMPUTERNAME}</Build-Machine>
<Build-Date>${maven.build.timestamp}</Build-Date>
</manifestEntries>
</archive>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>deploy</phase>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>install</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.paulius.hibernateviajpa.util.HibernateDDLGenerator</mainClass>
<arguments>
<argument>${project.basedir}/target/schema.sql</argument>
<argument>com.paulius.hibernateviajpa.entity</argument>
<argument>org.hibernate.dialect.MySQLDialect</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
- Creating Persistence configuration file
Under
../resources/META-INF/ folder create
persistence.xml file. The
persistence.xml file is a standard configuration
file in JPA. It has to be included in the
META-INF
directory inside of the web application archive that contains the entity beans. The
persistence.xml file must define a
persistence-unit with a unique name. The provider
element specifies the underlying implementation of the
JPA EntityManager
which in our case is
Hibernate. Class element defines
full java class name. This class must be persistence entity.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="entityManager" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.paulius.hibernateviajpa.entity.Account</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<validation-mode>NONE</validation-mode>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
- Creating Spring application context file and configuring EntityManager
Under
../webapp/WEB-INF/ folder create a file named
applicationContext.xml.
<?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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.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">
<context:component-scan base-package="com.paulius.hibernateviajpa"/>
<mvc:annotation-driven/>
<bean id="jdbcPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:project.properties"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="persistenceUnitName" value="entityManager"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
- Creating project properties file for JDBC configuration
Under
../resources/ folder create a file named
project.properties.
#JDBC configuration
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/hibernate_via_jpa?useEncoding=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
- Creating Spring dispatcher context file
Under ../webapp/WEB-INF/ folder create a file named dispatcher-servlet.xml.
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.htm">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index"/>
</beans>
- Creating web application deployment descriptor
Under
../webapp/WEB-INF/ folder create a file named
web.xml.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
- Creating redirect.jsp file
Under
../webapp/ folder create a file named
redirect.jsp. All views should be stored under the
WEB-INF folder so that they are not accessible except through controller process. This
JSP is here to provide a redirect to the dispatcher servlet but should be the only
JSP outside of
WEB-INF.
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<% response.sendRedirect("index.htm"); %>
- Creating the main view file
Under
../webapp/WEB-INF/views/ folder create a file named
index.jsp.
<!DOCTYPE html>
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--@elvariable id="accounts" type="java.util.List<com.paulius.hibernateviajpa.entity.Account>"--%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hibernate Via JPA Example</title>
<style type="text/css">
.label {
display: block;
}
</style>
</head>
<body>
<h1>Hibernate Via JPA Example Application</h1>
<form:form action="${pageContext.servletContext.contextPath}/index.htm" commandName="index">
<div>
<form:label cssClass="label" path="name">Name: </form:label>
<form:input path="name"/>
</div>
<div>
<form:label cssClass="label" path="email">Email address: </form:label>
<form:input path="email"/>
</div>
<div>
<form:label cssClass="label" path="username">Username: </form:label>
<form:input path="username"/>
</div>
<div>
<form:label cssClass="label" path="password">Password: </form:label>
<form:password path="password"/>
</div>
<div>
<input type="submit" value="Register user"/>
</div>
</form:form>
<hr/>
<div>
<a href="${pageContext.servletContext.contextPath}/index/show-users.htm">Show all users</a>
<c:if test="${not empty accounts}">
<div>
<h3>Registered Users:</h3>
<table border="1">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<c:forEach var="account" items="${accounts}">
<tr>
<td><c:out value="${account.name}"/></td>
<td><c:out value="${account.email}"/></td>
<td><c:out value="${account.username}"/></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</c:if>
</div>
</body>
</html>
- Creating BaseEntity class. The parent class of all the entities
Create a class:
com.paulius.hibernateviajpa.entity.BaseEntity.
This class is the parent class of all the entities in this application. This example contains only one: Account entity. Choosing to use inheritance in JPA it is up to a developer. I prefer this approach so that the primary key of the entity is coming from the parent class and you don't have to define it in each entity.
package com.paulius.hibernateviajpa.entity;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;
public Long getId() {
return id;
}
}
- Creating Account class
Create a class:
com.paulius.hibernateviajpa.entity.Account.
This class represents a user in the database.
package com.paulius.hibernateviajpa.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name = "ACCOUNT")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Account extends BaseEntity {
@Column(name = "NAME", nullable = false)
private String name;
@Column(name = "EMAIL", nullable = false)
private String email;
@Column(name = "USERNAME", nullable = false)
private String username;
@Column(name = "PASSWORD", nullable = false)
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- Creating AbstractFacade class to perform JPA operations
Create a class:
com.paulius.hibernateviajpa.facade.AbstractFacade.
This class is a generic class and has to be inherited by all other Facade class. In this case only one AccountFacade is extending this class. This approach has been chosen because this class defines only generic methods like: create, find, edit, delete - the standard operations which most likely is going to be used among most of the entities. To have a separate facade for other entities is a benefit so that these methods are used from the parent class and all other - entity specific method is created in the specific facade.
package com.paulius.hibernateviajpa.facade;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
import java.util.List;
@SuppressWarnings("unchecked")
public abstract class AbstractFacade<T> {
@PersistenceContext(unitName = "entityManager")
private EntityManager entityManager;
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
public AbstractFacade() {
}
protected EntityManager getEntityManager() {
return this.entityManager;
}
public void create(T entity) {
this.entityManager.persist(entity);
}
public void edit(T entity) {
this.entityManager.merge(entity);
}
public void remove(T entity) {
this.entityManager.remove(this.entityManager.merge(entity));
}
public T find(Long primaryKey) {
return this.entityManager.find(entityClass, primaryKey);
}
public List<T> findAll() {
CriteriaQuery cq = this.entityManager.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return this.entityManager.createQuery(cq).getResultList();
}
}
- Creating AccountFacade class to perform JPA operations related to Account entity
Create a class:
com.paulius.hibernateviajpa.facade.AccountFacade.
This class is used to perform operation for the specific entity.
package com.paulius.hibernateviajpa.facade;
import com.paulius.hibernateviajpa.entity.Account;
import org.springframework.stereotype.Repository;
@Repository
public class AccountFacade extends AbstractFacade<Account> {
public AccountFacade() {
super(Account.class);
}
}
- Creating user RegistrationForm model attribute class
Create a class:
com.paulius.hibernateviajpa.form.RegistrationForm.
This class is used as
Spring model attribute which refers to a property of the
Model object.
package com.paulius.hibernateviajpa.form;
import java.io.Serializable;
public class RegistrationForm implements Serializable {
private String name;
private String email;
private String username;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- Creating user RegistrationController class
Create a class:
com.paulius.hibernateviajpa.controller.RegistrationController.
This class is used to create actual user and store his details in the database. Also it has a facility to retrieve all users later to be displayed in the view.
package com.paulius.hibernateviajpa.controller;
import com.paulius.hibernateviajpa.entity.Account;
import com.paulius.hibernateviajpa.facade.AccountFacade;
import com.paulius.hibernateviajpa.form.RegistrationForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
import java.util.Map;
@Controller
public class RegistrationController {
@Autowired
private AccountFacade accountFacade;
@RequestMapping(value = "index", method = RequestMethod.GET)
public String showMainView() {
return "index";
}
@ModelAttribute("index")
public RegistrationForm getRegistrationForm() {
return new RegistrationForm();
}
@Transactional
@RequestMapping(value = "index", method = RequestMethod.POST)
public String processRegisterUser(@ModelAttribute("index") RegistrationForm form) {
Account account = new Account();
account.setName(form.getName());
account.setEmail(form.getEmail());
account.setUsername(form.getUsername());
account.setPassword(form.getPassword());
accountFacade.create(account);
return "index";
}
@Transactional
@RequestMapping(value = "index/show-users", method = RequestMethod.GET)
public String showAllUsers(Map<String, Object> model) {
List<Account> accounts = accountFacade.findAll();
model.put("accounts", accounts);
return "index";
}
}
- Creating HibernateDDLGenerator class
Create a class:
com.paulius.hibernateviajpa.util.HibernateDDLGenerator.
This class is used to generate MySQL schema - SQL queries to create all tables, indexes, foreign keys. Depending on the provided dialect Hibernate will generate SQL queries for the specific engine. In this case MySQL is used so it will be MySQL queries. Sometimes people are using Hibernate to update database schema automatically once application is being deployed - this is unsafe and definitely should not be used in production, because you don't know what Hibernate is doing in the background and you can't rely on automatic updates, you have to be in control of that yourself. The main method of this class will be called when Maven install command is executed and generated schema will be placed under: ${project.basedir}/target/schema.sql.
package com.paulius.hibernateviajpa.util;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
public class HibernateDDLGenerator {
public static void main(String[] args) {
execute(args[0], args[1], args[2]);
}
private static Iterable<Class> getClasses(String packageName)
throws ClassNotFoundException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = packageName.replace('.', '/');
Enumeration<URL> resources = classLoader.getResources(path);
LinkedList<File> dirs = new LinkedList<>();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
LinkedList<Class> classes = new LinkedList<>();
for (File directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
return classes;
}
private static LinkedList<Class> findClasses(File directory, String packageName)
throws ClassNotFoundException {
LinkedList<Class> classes = new LinkedList<>();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
classes.addAll(findClasses(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add(Class.forName(
packageName + '.'
+ file.getName().substring(0, file.getName().length() - 6)));
}
}
}
return classes;
}
private static LinkedList<Class> findAnnotatedClasses(String packageName) {
LinkedList<Class> classes = new LinkedList<>();
try {
for (Class clazz : getClasses(packageName)) {
classes.add(clazz);
}
} catch (ClassNotFoundException ex) {
throw new RuntimeException("Class not found exception occurred.", ex);
} catch (IOException ex) {
throw new RuntimeException("IO exception occurred.", ex);
}
return classes;
}
private static void execute(String fileName, String packageName, String dialect) {
Configuration configuration = new Configuration();
configuration.setProperty(Environment.DIALECT, dialect);
for (Class<?> entityClass : findAnnotatedClasses(packageName)) {
configuration.addAnnotatedClass(entityClass);
}
SchemaExport schemaExport = new SchemaExport(configuration);
schemaExport.setDelimiter(";");
schemaExport.setOutputFile(fileName);
schemaExport.setFormat(false);
schemaExport.create(false, false);
}
}
Once all the above listed files have been created you are ready to build and deploy your application. Don't forget that before deploying it database has to be created. In the project.properties file there is
JDBC configuration which most likely will be changed. Before deploying the application you have to create the database named: hibernate_via_jpa and execute the following query which has been generated by HibernateDDLGenerator during Maven install phase:
CREATE TABLE ACCOUNT (
ID BIGINT NOT NULL AUTO_INCREMENT,
EMAIL VARCHAR(255) NOT NULL,
NAME VARCHAR(255) NOT NULL,
PASSWORD VARCHAR(255) NOT NULL,
USERNAME VARCHAR(255) NOT NULL,
PRIMARY KEY (ID));
Once the query has been executed your database is ready. Start up
Tomcat and deploy your application via
Tomcat manager. Once application has been deployed open the browser:
http://localhost:8080/hibernate-via-jpa/index.htm (I am assuming that your host is
localhost and port
8080) and you will see the following window:
Create a user by entering some details in the form fields. Please note, that there are no validation and you have to specify values for all the fields. Once you have created a user, you can click on the link "
Show all users" and all users will be listed in the table just after this link like displayed below: