Spring JPA, Hibernate, Data XML configuration

Here’s a cleaned up, plug’n’play version of a Spring database XML config taken from a demo project employing Spring Data for the Repositories interfaces and Hibernate behind JPA.

<beans 	xmlns="http://www.springframework.org/schema/beans"
		xmlns:p="http://www.springframework.org/schema/p"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/data/jpa
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		  p:entityManagerFactory-ref="entityManagerFactory" />


	<jpa:repositories base-package="com.to.my.data.repository"
					  transaction-manager-ref="transactionManager"
					  entity-manager-factory-ref="entityManagerFactory"/>

	<tx:annotation-driven transaction-manager="transactionManager"/>
	

	
	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
					p:database="${database.database}"
					p:databasePlatform="${database.databasePlatform}"
					p:showSql="${database.showSql}"
					p:generateDdl="${database.generateDdl}" />
		</property>
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.dialect">${database.databasePlatform}</prop>
				<prop key="hibernate.max_fetch_depth">3</prop>
				<prop key="hibernate.fetch_size">50</prop>
				<prop key="hibernate.batch_size">10</prop>
				<prop key="hibernate.show_sql">true</prop>
			</props>
		</property>
		<property name="packagesToScan" value="com.to.my.bean"/>
	</bean>
	
	<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource"
			p:driverClassName="${database.driverClassName}"
			p:url="${database.url}"
			p:username="${database.username}"
			p:password="${database.password}"
			p:testOnBorrow="true"
			p:testOnReturn="true"
			p:testWhileIdle="true"
			p:timeBetweenEvictionRunsMillis="1800000"
			p:numTestsPerEvictionRun="3"
			p:minEvictableIdleTimeMillis="1800000"
			p:initialSize="1"
			p:maxActive="50"
			p:maxIdle="20"/>

</beans>
Advertisements

Spring, Hibernate, MySQL integration example

This is a working example showcasing Spring, Hibernate and MySQL integration in a Maven project.

The POM looks like this:

<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.dimitrisli</groupId>
  <artifactId>SpringMySQL</artifactId>
  <version>1.0</version>
  <build>
  	<finalName>SpringHibernateMySQL</finalName>
  	<plugins>
  		<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-compiler-plugin</artifactId>
  			<version>2.3.2</version>
  			<configuration>
  				<source>1.6</source>
  				<target>1.6</target>
  				<encoding>UTF-8</encoding>
  			</configuration>
  		</plugin>
  	</plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.18</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>3.1.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
	<dependency>
	  <groupId>org.hibernate</groupId>
	  <artifactId>hibernate-core</artifactId>
	  <version>3.6.9.Final</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-orm</artifactId>
		<version>3.1.0.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>javassist</groupId>
		<artifactId>javassist</artifactId>
		<version>3.12.1.GA</version>
	</dependency>
  </dependencies>
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

Our MySQL database script:

create database javaTestDB;
use javaTestDB;
CREATE USER javauser IDENTIFIED BY 'javapass';
grant usage on *.* to javauser@localhost identified by 'javapass';
grant all privileges on javaTestDB.* to javauser@localhost;

CREATE TABLE PERSON_RECORD (
	ID INT NOT NULL AUTO_INCREMENT,
	NAME VARCHAR(15) NOT NULL,
	SURNAME VARCHAR(15) NOT NULL,
	PRIMARY KEY (ID)
);

This is basically a table that is representing our Person Java bean:

package com.dimitrisli.springHibernateMySQL.model;

import java.io.Serializable;

public class Person implements Serializable {

	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private String surname;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSurname() {
		return surname;
	}
	public void setSurname(String surname) {
		this.surname = surname;
	}

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

	public Integer getId(){
		return this.id;
	}
}

Each DB table record represents a Person Object. The Person CRUD operations are represented in this interface:

package com.dimitrisli.springHibernateMySQL.dao;

import com.dimitrisli.springHibernateMySQL.model.Person;

public interface PersonORMDao {

	public void create(Person person);
	public Person read(String name, String surname);
	public void update(Person person);
	public void delete(Person person);
}

Since we are using Spring it’s a good practise to have an associated interface for every DAO bean we are planning to have since Spring behind the scenes is creating a proxy between this interface and the POJO before creating the bean.

The implementation of this interface looks like this:

package com.dimitrisli.springHibernateMySQL.dao;

import java.util.List;

import com.dimitrisli.springHibernateMySQL.model.Person;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class PersonDaoHibernateImpl extends HibernateDaoSupport implements PersonORMDao{

	public void create(Person person) {
		getHibernateTemplate().save(person);
	}

	public Person read(String name, String surname) {
		List list = getHibernateTemplate().find("from PERSON_RECORD where NAME=? AND SURNAME=?",name,surname);
		return (Person) list.get(0);
	}

	public List readAll() {
		List list = getHibernateTemplate().find("from " + Person.class.getName());
		return list;
	}

	public void update(Person person) {
		getHibernateTemplate().update(person);
	}

	public void delete(Person person) {
		getHibernateTemplate().delete(person);
	}

	public void deleteAll() {
		getHibernateTemplate().deleteAll(readAll());
	}
}

Notice that this DAO implementation is extending from HibernateDaoSupport which is a Spring Hibernate convenience abstract class and is using its getHibernateTemplate() for all the data access operations. Also notice the hibernate query language (HQL) to express sql where conditions.

We’ll pack the property related files under src/main/resources grouped in meaningful folders maintaining a good housekeeping.

The Hibernate related DB mapping into is maintained under resources/hibernate/person.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.dimitrisli.springHibernateMySQL.model.Person" table="PERSON_RECORD">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="NAME" length="15" not-null="true" unique="false" />
        </property>
        <property name="surname" type="string">
            <column name="SURNAME" length="15" not-null="true" unique="false" />
        </property>
    </class>
</hibernate-mapping>

MySQL related information like the driver name, the connection URL, the username/pass are found in the resources/properties/database.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/javaTestDB
jdbc.username=javauser
jdbc.password=javapass

The database related beans are stored in resources/spring/database/database.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
	<property name="location">
		<value>properties/database.properties</value>
	</property>
</bean>

<bean id="dataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	<property name="driverClassName" value="${jdbc.driverClassName}" />
	<property name="url" value="${jdbc.url}" />
	<property name="username" value="${jdbc.username}" />
	<property name="password" value="${jdbc.password}" />
</bean>

</beans>

Things to notice:

  • Spring’s PropertyPlaceholderConfigurer is conveniently reading the database properties and make them available to the datasource bean.

The Hibernate session factory represented in a LocalSessionFactoryBean is stored in the resources/spring/database/hibernate.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource">
      <ref bean="dataSource"/>
    </property>
    <property name="hibernateProperties">
       <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
         <prop key="hibernate.show_sql">true</prop>
       </props>
     </property>
 	 <property name="mappingResources">
		<list>
           <value>/hibernate/person.hbm.xml</value>
		</list>
     </property>
    </bean>
</beans>

Note how the mapping config file is loaded as a property on the bean. Also how we are activating the HQL and show the output.

the final configuration file is gathering all the resources and found in resources/spring/config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
	<import resource="../database/datasource.xml" />
	<import resource="../database/hibernate.xml" />
 	<import resource="../beans/beans.xml" />
 	
</beans>

Finally the test class that is creating the application context and making some basic demonstration queries:

package com.dimitrisli.springHibernateMySQL.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.dimitrisli.springHibernateMySQL.dao.PersonDaoHibernateImpl;
import com.dimitrisli.springHibernateMySQL.model.Person;

public class Main {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring/config/beanLocations.xml");
		PersonDaoHibernateImpl personDao = (PersonDaoHibernateImpl) context.getBean("personHibernateDao"); 
		
		System.out.println("Adding data...");
		Person dimitris = new Person(); dimitris.setName("dimitris"); dimitris.setSurname("liapis");
		Person michalis = new Person(); michalis.setName("michalis"); michalis.setSurname("liapis");
		Person kostas = new Person(); kostas.setName("kostas"); kostas.setSurname("liapis");
		Person stella = new Person(); stella.setName("stella"); stella.setSurname("liapis");
		personDao.create(dimitris);
		personDao.create(michalis);
		personDao.create(kostas);
		personDao.create(stella);
		
		System.out.println("Retrieving data..");
		for(Person currentPerson : personDao.readAll()){
			System.out.println("From DB: name="+currentPerson.getName()+", surname="+currentPerson.getSurname());
		}
		
		System.out.println("Deleting a record and viewing...");
		personDao.delete(kostas);
		for(Person currentPerson : personDao.readAll()){
			System.out.println("From DB: name="+currentPerson.getName()+", surname="+currentPerson.getSurname());
		}
		
		System.out.println("Updating a record and viewing...");
		dimitris.setName("newDimitrisName");
		personDao.update(dimitris);
		for(Person currentPerson : personDao.readAll()){
			System.out.println("From DB: name="+currentPerson.getName()+", surname="+currentPerson.getSurname());
		}
		
		System.out.println("Deleting everything and viewing...");
		personDao.deleteAll();
		for(Person currentPerson : personDao.readAll()){
			System.out.println("From DB: name="+currentPerson.getName()+", surname="+currentPerson.getSurname());
		}
		
	}
}

The output, subtracting the initialisation coding of the frameworks, looks like this:

Adding data...
Hibernate: insert into PERSON_RECORD (NAME, SURNAME) values (?, ?)
Hibernate: insert into PERSON_RECORD (NAME, SURNAME) values (?, ?)
Hibernate: insert into PERSON_RECORD (NAME, SURNAME) values (?, ?)
Hibernate: insert into PERSON_RECORD (NAME, SURNAME) values (?, ?)
Retrieving data..
Hibernate: select person0_.ID as ID0_, person0_.NAME as NAME0_, person0_.SURNAME as SURNAME0_ from PERSON_RECORD person0_
From DB: name=newDimitrisName, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=stella, surname=liapis
From DB: name=dimitris, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=kostas, surname=liapis
From DB: name=stella, surname=liapis
Deleting a record and viewing...
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: select person0_.ID as ID0_, person0_.NAME as NAME0_, person0_.SURNAME as SURNAME0_ from PERSON_RECORD person0_
From DB: name=newDimitrisName, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=stella, surname=liapis
From DB: name=dimitris, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=stella, surname=liapis
Updating a record and viewing...
Hibernate: update PERSON_RECORD set NAME=?, SURNAME=? where ID=?
Hibernate: select person0_.ID as ID0_, person0_.NAME as NAME0_, person0_.SURNAME as SURNAME0_ from PERSON_RECORD person0_
From DB: name=newDimitrisName, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=stella, surname=liapis
From DB: name=newDimitrisName, surname=liapis
From DB: name=michalis, surname=liapis
From DB: name=stella, surname=liapis
Deleting everything and viewing...
Hibernate: select person0_.ID as ID0_, person0_.NAME as NAME0_, person0_.SURNAME as SURNAME0_ from PERSON_RECORD person0_
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: delete from PERSON_RECORD where ID=?
Hibernate: select person0_.ID as ID0_, person0_.NAME as NAME0_, person0_.SURNAME as SURNAME0_ from PERSON_RECORD person0_

The source code can be found in this Github repository.