Simple Maven2, Spring 2.5, JPA and Hibernate integration

A few months ago, i’ve read a tutorial about spring 2.5 writen by Endy Muhardin (one of JUG Indonesia Hall Of Fame), that tutorial explained bout newest features of Spring 2.5, this version now supports Annotation. Configuration is no longer always in xml file. this made our effort to build program pragmatically  more easier to configure, faster and efficient.

But due to my bustle, and a regulation in place i work now. i have to leave Spring Frameworks. My project prefer choosing EJB3 and Struts2 as main developtment stack. the main reason is our client need a distributable application (even i know that spring support those too). Besides, developt a  ORM for handling database using JPA is more interesting for me than other approach. One question is, how bout people who doesnt need EJB feature which needed heavy container like Glassfish or JBOSS to running their application?.

Fortunately, Spring support JPA for connecting  to database, we can choose Hibernate or Toplink for JPA implementations. and it’s still can run in light web server like tomcat or jetty.  i’ll give you very simple example using JPA+Hibernate in Spring 2.5.

I’m using apache-maven2 for build this program, you can download it here and read this tutorial for installation.

Let me assume you have using maven2 before. Because we using Hibernate-Annotation, we need create a POJO class references from our table in database. All entity class must be registered with @Entity annotation. in Person class below i have added named query. it can be used if we want create costum query beside delete, update or persist (create) data.

package org.thenest.simplespring.models;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name = "PERSON")
@NamedQueries( { @NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p") })
public class Person {
	private int id;
	private String name;
	private int age;

	public void setId(int id) {
		this.id = id;
	}

	@Id
	public int getId() {
		return id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
}

And this is DDL file for create table PERSON (i’m using mysql), and insert data into thus table.

CREATE TABLE PERSON(
	ID INT(5) PRIMARY KEY NOT NULL AUTO_INCREMENT,
	NAME VARCHAR(50) NOT NULL,
	AGE INT(3) NOT NULL);

INSERT INTO PERSON values(NULL,'Michael','22');
INSERT INTO PERSON values(NULL,'Alex','23');
INSERT INTO PERSON values(NULL,'Kevin','19');

One DAO class interface and it’s implementations. we can notice that PersonServiceJpa class have @Repository annotation. it’s mean we doesn’t needed to register this DAO class in Spring’s application context. We gonna make all DAO auto scanned.

package org.thenest.simplespring.services;

import java.util.List;

import org.thenest.simplespring.models.Person;

public interface IPersonService {
	public boolean save(Person person);
	public List<Person> getAll();
	public Person getById(int id);
	public boolean delete(Person person);
	public boolean update(Person person);
}

package org.thenest.simplespring.services.jpa;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.thenest.simplespring.models.Person;
import org.thenest.simplespring.services.IPersonService;

@Repository("iPersonService")
@Transactional(readOnly = true)
public class PersonServiceJpa implements IPersonService {

	private EntityManager entityManager;

	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	@Override
	public Person getById(int id) {
		// TODO Auto-generated method stub
		return entityManager.find(Person.class, id);
	}

	public List<Person> getAll() {
		Query query = entityManager.createNamedQuery("Person.findAll");
		List&amp;lt;Person&amp;gt; persons = null;
		persons = query.getResultList();
		return persons;
	}

	@Override
	public boolean save(Person person) {
		entityManager.persist(person);
		entityManager.flush();
		return true;
	}

	@Override
	public boolean update(Person person) {
		entityManager.merge(person);
		entityManager.flush();
		return true;
	}

	@Override
	public boolean delete(Person person) {
		person = entityManager.getReference(Person.class, person.getId());
		if (person == null)
			return false;
		entityManager.remove(person);
		entityManager.flush();
		return true;
	}
}

And persistence.xml file :

<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_1_0.xsd"
		version="1.0">

	<persistence-unit name="testa" transaction-type="RESOURCE_LOCAL">
        <class>org.thenest.simplespring.models.Person</class>
    </persistence-unit>
</persistence>

Here they are application context, you need to change dataSource setting with your locat variable.

<?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"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
			http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

	<context:annotation-config />
	<context:component-scan base-package="org.thenest.simplespring.services" />
	<tx:annotation-driven />
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
		p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost/iseng"
		p:username="root" p:password="rahasia" />
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
		p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
		<property name="loadTimeWeaver">
			<bean
				class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
		</property>
	</bean>
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		p:entityManagerFactory-ref="entityManagerFactory" />
	<bean id="jpaAdapter"
		class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
		p:database="MYSQL" p:showSql="true" />
</beans>

Cause i’m using JUnit too for unit testing, this is unit testing class. i assume you have using JUnit too before.

package test.org.thenest.simplespring;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.thenest.simplespring.models.Person;
import org.thenest.simplespring.services.IPersonService;

public class PersonDaoSpringJpaTest {

	private ApplicationContext ctx;
	private IPersonService personService;
	private Logger log = Logger.getLogger(this.getClass());

	public PersonDaoSpringJpaTest() {
		BasicConfigurator.configure();
		// TODO Auto-generated constructor stub
		ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		personService = (IPersonService) ctx.getBean("iPersonService");
		log.info("Application Context Loaded");
	}

	@Test
	public void testGetAll() {
		log.info("Test get all =================================");
		for (Person p : personService.getAll()) {
			log.info("Name : " + p.getName() + " Age " + p.getAge());
		}
	}

	@Test
	public void testSave() {
		log.info("Test Save Data =================================");
		Person person = new Person();
		person.setName("Raven");
		person.setAge(23);
		personService.save(person);
	}

	@Test
	public void testGetDataById() {
		log.info("Test get data by id ==========================");
		Person p = personService.getById(1);
		log.info("Name : " + p.getName() + " Age " + p.getAge());

	}

	@Test
	public void testUpdateData() {
		log.info("Test update data =============================");
		Person p = personService.getById(1);
		log.info("Name : " + p.getName() + " Age " + p.getAge());
		p.setAge(30);
		personService.update(p);

	}

	@Test
	public void testDeleteData() {
		log.info("Test delete all ==============================");
		Person p = personService.getById(1);
		personService.delete(p);

	}
}

And last, Maven 2 build file, pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>SimpleSpringJpaHibernateApp</groupId>
	<artifactId>SimpleSpringJpaHibernateApp</artifactId>
	<packaging>jar</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<description></description>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<executable>${JAVA_HOME}/bin/javac
					</executable>
					<compilerVersion>1.6</compilerVersion>
					<source>1.6</source>
					<target>1.6</target>
					<debug>true</debug>
					<fork>true</fork>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.9</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring</artifactId>
			<version>2.5.4</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>2.5.5</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>
		<dependency>
			<groupId>hsqldb</groupId>
			<artifactId>hsqldb</artifactId>
			<version>1.8.0.7</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager
			</artifactId>
			<version>3.3.2.GA</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.4</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.6</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.2</version>
		</dependency>
	</dependencies>
</project>

You can download all complete code here . If you wan’t to integrating Spring without JPA bridge, I’ve already short tutorial about Spring 3.0 and Hibernate here

About singgihpraditya

Gua cuma orang biasa, gak lebih , gak kurang. code maniac (i've been entrust all whole live just to make a good code)
This entry was posted in Java. Bookmark the permalink.

6 Responses to Simple Maven2, Spring 2.5, JPA and Hibernate integration

  1. Kasim says:

    That’s really what I want!

    Thank you very much for your kindly sharing!

  2. Kasim says:

    By the way, I suggest you can use dbunit and hibernate3 hbm3ddl to create datebase schema and inject data into the database using maven.

  3. singgihpraditya says:

    Hi Kasim
    Thanks for your suggestion, glad to help you

  4. McG says:

    The code above bombed on me at:
    personService = (IPersonService) ctx.getBean(“iPersonService”);

    It seems there is no such bean declared in the above spring config file.

  5. McG says:

    Ahh… it was a typo causing issue. Your code works fine…

  6. Pingback: Spring 3.0 and Hibernate tutorial (part 1) « Me and my chaotic life

Leave a comment