Saturday, September 7, 2013

Spring Data - JPA

A lot of effort is required for configuration and using JPA. Spring Data JPA has reduced that to a major extent. Takes little effort to configure and easy to use. Let's look at this with an example.
The spring data dependency and hibernate dependencies using maven are as follows. (Note: All other spring core, bean, context dependencies are required along with the below dependencies)
        <!-- Spring Data JPA -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.0.2.RELEASE</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
Create a persistence xml file in META-INF file.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <!--Persistence Unit for Mysql database-->
    <persistence-unit name="testMysql" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>com.test.entity.Employee</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>
Now, need to configure Spring Data - JPA using the persistent unit "testMysql"
<?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:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Following data source for Mysql-->
    <bean id="mysqltestDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.testurl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--Following entity manager for Mysql database-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="mysqltestDataSource"/>
        <property name="persistenceUnitName" value="testMysql"/>
    </bean>

    <!--Transaction manager for both H2 and Mysql-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    
    <jpa:repositories transaction-manager-ref="transactionManager" 
        entity-manager-factory-ref="entityManagerFactory" base-package="com.test.dao">
    </jpa:repositories>
    
</beans>
Explanation of above spring configuration Create one datasource.

  • Create one driver manager datasource named "mysqltestDataSource", by loading jdbc.properties file from the classpath using line <context:property-placeholder location="classpath:jdbc.properties"/>
  • Create entity manager factory using the datasource created and persistent unit created in persistent.xml
  • Inject entity manager factory into transaction manager. 
  • Finally configure both transaction manager and entity manager factory to set of repositories in a package (defined using base-package)
Now, create repository, an interface which extends JpaRepository inside package (defined in base-package). The typed arguments required are one entity and other is Id. In this case, entity is Employee and Id of the Employee is Long.
package com.test.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.test.entity.Employee;

public interface EmployeeDAO extends JpaRepository<Employee, Long>
{
}
The entity is as follows
package com.test.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "EMP")
@Entity
public class Employee
{
    private int id;
    private String name;
    private int age;
    @Id
    @Column(name = "id", unique = true, nullable = false)
    public int getId()
    {
        return id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
    @Column(name = "name")
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    @Column(name = "age")
    public int getAge()
    {
        return age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
}
That's it on the configuration part. By using the repository, we can do all types of database operations for that entity. There are numberous in-built methods are provided by JpaRepository interface. Sample code for that will be
        EmployeeDAO dao = (EmployeeDAO)context.getBean("employeeDAO");
        List list = dao.findAll();
        for(Employee e : list)
        {
            //Do Something
        }