Saturday, May 04, 2013

Spring 3 Part 8: Spring Hibernate open session in view

This is the 8th part of the Spring 3 Series.
In this blog I am going to use Hibernate 3.5.2 to explain the use of Spring Transaction which fulfil the requirements of open session in view pattern. First understand some important concepts in Hibernate. First of all, it is very important to understand the object states in the Hibernate. Transient object will become a persistent object in the context of active session. This persistent object represent one row of the data table. There can be two transient object references which are not refer to the same object but can hold same data. These objects are identical only in the persistence context (persistent objects are identical) because persistence objects are identified based on the database primary key. Therefore, persistence object identifier is the same as data table identifier.  For the transient and detached object, equal() and hashcode() are the methods to be implemented to define the identifier.
finaloutput
Figure 1: Hibernate Entity Status

Transient object can be created using new operator. The main thing is it is not associated with a Hibernate session. Transient object will be destroyed by the GC when all the references are released.
Persistent object can be created using Transient object when transient object is associated with a Hibernate session by save/persist() or load() operations. Hibernate synchronize the state of the persistent object with the database.
Detached object is a persistent object without associated a Hibernate session (when session is closed). The detached object can be modified and attach back to the to a new Hibernate session later.

  persistent representation Identifier value
Transient
no
equal, hashcode
Persistent
yes
primary key
Detached
no
equal, hashcode
It is important to understand the Hibernate session factory here on SessionFactory.  SessionFactory a thread safe immutable cache of compiled mapping  for single database. SessionFactory optionaly maintains optional second-level cache for the data (for process or cluster) . This is the factory to create a Hibernate Session.
ENIMAGE1367584595211
Figure 2: Hibernate Session from SessionFactory
Hibernate Session is single threaded as well as it is design to be short live. it wrap the database connection and the factory for the org.hibernate.Transaction. Session is responsible to maintain the first level cache which hold the the persistent object graph and graph navigation (persistence context). Session wrap the connection.
This is not a web based application ( which complicate our discussion) instead standard Java application. For standard Java application, Hibernate recommended the Session handling with AOP.  The basic question is
What is the advantage of use of Spring for standard Java based Hibernate application ?
In this blog my objective to emphasis this advantage.
“ Use of Spring transactions completely avoid the use of AOP based Session handling, because Spring transactions are itself AOP implementations. “
This application is layered to 4 layers: Client, Service, DAO and Persistence. Although DAO is not recommended, for simplicity I use DAO layer
First consider the Persistence layer for the schema explained in the pervious blog: Spring 3 Part 7: Spring with Databases.
image

Here the State,
package au.com.ojitha.blogspot.spring.part8.domain;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class State implements Serializable {


    private String code;
    private String state;
    private int version;
    
    @Id
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    
    public int getVersion() {
        return version;
    }
    public void setVersion(int version) {
        this.version = version;
    }
    
}
Here the Address Entity
package au.com.ojitha.blogspot.spring.part8.domain;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;

@Entity
@NamedQuery(name="Address.findAll", query="select a from Address a left join fetch a.state")
public class Address implements Serializable {

    @Id
    private int id;
    
    @Column(name="STREET_NUMBER")
    private String street;
    
    private String suburb;
    
    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    @JoinColumn(name="STATE")
    private State state;
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    public String getSuburb() {
        return suburb;
    }
    public void setSuburb(String suburb) {
        this.suburb = suburb;
    }
    public State getState() {
        return state;
    }
    public void setState(State state) {
        this.state = state;
    }
    
    

}
As shown in the line 27, FetchType.LAZY configure the one to one relationship to access the State when only necessary. In other words, although you initiate the Address Entity, the state property is still null until properties of the state property is first time accessed. The most important thing is this state property should be accessed within the same session. Next consider the DAO layer, although I have two DAOs, in this example I use only AddressDAO.
image

Here the DAO interface, which hold all the CURD operations common to all the DAO implmenations
package au.com.ojitha.blogspot.spring.part8.dao;

import java.util.List;

public interface Dao<T, PK> {
    List<T> findAll();
    T findByPk(PK pk);
}
For Address, the DAO is AddressDAO
package au.com.ojitha.blogspot.spring.part8.dao;


public interface AddressDao<T, PK> extends Dao<T, PK> {
    
}
For the AddressDao , here the implementation
package au.com.ojitha.blogspot.spring.part8.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import au.com.ojitha.blogspot.spring.part8.domain.Address;

@Repository("addressDao")
@Transactional
public class AddressDaoImpl implements AddressDao<Address, Integer> {

    @Resource(name="sessionFactory")
    SessionFactory sessionFactory;
    
    @Transactional(readOnly=true)
    public List<Address> findAll() {
        return sessionFactory.getCurrentSession().createQuery("from Address a").list();
        //return sessionFactory.getCurrentSession().getNamedQuery("Address.findAll").list();
    }

    public Address findByPk(Integer pk) {
        // TODO Auto-generated method stub
        return null;
    }

}
In the above code, only the findAll() method is implemented. As shown in the figure 2, Session is reused using getCurrentSession() as stated in the line 22. AdddressDaoImpl doesn’t create new session because transaction was propagated from the Address service. SessionFactory is the factory for Hibernate session.
image
As shown in the above class diagram, Service layer, consist of AddressService and the Client layer consists of Client classes. AddressServiceImpl access the AddressDao which is already explained under the DAO Layer.
package au.com.ojitha.blogspot.spring.part8.service;

import java.util.List;

import au.com.ojitha.blogspot.spring.part8.domain.State;



public interface AddressService {
    /**
     * All the states from the {@link State}.
     * @return array of States.
     */
    public List<State> getAllStates();

}
And here the Implementation,
package au.com.ojitha.blogspot.spring.part8.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Hibernate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import au.com.ojitha.blogspot.spring.part8.dao.AddressDao;
import au.com.ojitha.blogspot.spring.part8.domain.Address;
import au.com.ojitha.blogspot.spring.part8.domain.State;

@Repository("addressService")
@Transactional
public class AddressServiceImpl implements AddressService {
    
    @Resource(name="addressDao")
    AddressDao<Address, Integer> addressDao;
    
    
    @Transactional(readOnly=true)
    public List<State> getAllStates(){
        List<Address> addresses = addressDao.findAll();
        List<State> states = new ArrayList<State>();
        for (Address address : addresses) {
            State state = address.getState();
            Hibernate.initialize(state);
            states.add(state);
        }
        Hibernate.initialize(states);
        return states;
    }
}
It is necessary to highlight the line 24 Transaction annotation.  In this point, new transaction is created and propagated to the DAO: same session is available in the Service as well as AddressDao. In the line 30, before session completed, need to initialize the states because transaction state is not available in the Client who is the caller as shown in the following code.
package au.com.ojitha.blogspot.spring.part8.client;

import java.util.List;

import org.springframework.context.support.GenericXmlApplicationContext;

import au.com.ojitha.blogspot.spring.part8.dao.AddressDao;
import au.com.ojitha.blogspot.spring.part8.dao.StateDao;
import au.com.ojitha.blogspot.spring.part8.domain.Address;
import au.com.ojitha.blogspot.spring.part8.domain.State;
import au.com.ojitha.blogspot.spring.part8.service.AddressService;

public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.load("classpath:META-INF/spring/app-context.xml");
        ctx.refresh();
        
        AddressService service = ctx.getBean("addressService", AddressService.class);
        List<State> states = service.getAllStates();
        for (State state : states) {
            System.out.println(state.getState());
        }
    }

}
Whe initialize the stats, only second “select” will be executed as shown in the following log
2013-05-04 11:57:12,084 INFO [org.hibernate.impl.SessionFactoryObjectFactory] - <Not binding factory to JNDI, no JNDI name configured>
2013-05-04 11:57:12,313 INFO [org.springframework.orm.hibernate3.HibernateTransactionManager] - <Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@73d55dd] of Hibernate SessionFactory for HibernateTransactionManager>
2013-05-04 11:57:12,419 DEBUG [org.hibernate.SQL] - <select address0_.id as id0_, address0_.STATE as STATE0_, address0_.STREET_NUMBER as STREET2_0_, address0_.suburb as suburb0_ from Address address0_>
Hibernate: select address0_.id as id0_, address0_.STATE as STATE0_, address0_.STREET_NUMBER as STREET2_0_, address0_.suburb as suburb0_ from Address address0_
2013-05-04 11:57:12,446 DEBUG [org.hibernate.SQL] - <select state0_.code as code1_0_, state0_.state as state1_0_, state0_.version as version1_0_ from State state0_ where state0_.code=?>
Hibernate: select state0_.code as code1_0_, state0_.state as state1_0_, state0_.version as version1_0_ from State state0_ where state0_.code=?
Capital
As a conclusion, If you keep the transactional  persistence access open up to the Service layer, then the service layer is responsible for completing all the transactions (in Hibernate words, session). If you access the persistence object out of the Spring transaction as in the above example, it will throws Hibernate’s LazyInitializationException.
The source code for this blog is available to download from GitHub.

Wednesday, April 24, 2013

Spring 3 Part 7: Spring with Databases

This is the 7 th part of the Spring 3 Series.

Create MySQL 5.6 database ‘payroll’,

CREATE DATABASE payroll;

Next create a user for example, user ‘ojitha’

 CREATE USER 'ojitha'@'localhost' IDENTIFIED BY 'ojitha';

Need to grant the ‘payroll’ access to user ‘ojitha’ as shown in the following.

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON payroll.* TO 'ojitha'@'localhost';

You can download freeware of TOAD for MySQL from here.

image

Let create a first table, that contains all the states in Australia. You can create a table using visually using the icon given directly below the Tables tab in the Object Explorer as shown in the above diagram.

CREATE TABLE payroll.STATE (
CODE CHAR(3) ASCII COMMENT 'State code',
STATE VARCHAR(30),
PRIMARY KEY (CODE)
) ENGINE = InnoDB COMMENT = 'Australian states' ROW_FORMAT = DEFAULT;

In the my sql console you can the newly added table using the following command

SHOW TABLES;

However, I would recommend TOAD because it is nice tool to do all the kind of database stuff without pain.

CREATE TABLE payroll.ADDRESS (
ID INT,
STREET_NUMBER VARCHAR(20),
SUBURB VARCHAR(15) NOT NULL,
STATE CHAR(3) ASCII NOT NULL,
FOREIGN KEY (STATE) REFERENCES payroll.state (CODE) ON UPDATE RESTRICT ON DELETE RESTRICT,
PRIMARY KEY (ID)
) ENGINE = InnoDB COMMENT = 'Addresses' ROW_FORMAT = DEFAULT;

Relationships are shown in the following diagram

image

Let’s start with the easy example ‘state’.

Create DAO interface which holds CURD operations general for all the xxxDAOs

package au.com.ojitha.blogspot.spring3.part7;

import java.io.Serializable;
import java.util.List;

public interface DAO<T, K extends Serializable> {

//CURD operations
K create (T instance);
void update(T t);
T findByPrimaryKey(K id);
List<T> findAll();
void delete(T t);

}

In this example, we are going to implement DAO for the state: StateDAO which holds ‘state’ specific methods only. The ‘generic type declaration’ defines two type parameters, respectively type variable T for the return type that is State bean and the type variable K for the primary key that is String type.

package au.com.ojitha.blogspot.spring3.part7;

public interface StateDAO<State> extends DAO<State, String> {
public State getStateCode(String state);
}

As shown in the above code, ‘getStateCode’ specific to ‘state’. The StateDAO extends the DAO and generic type invocations are State and String as explained above.

Here, the Java Bean standard, State bean which will be used as type argument in the StateDAOImpl.

package au.com.ojitha.blogspot.spring3.part7;

public class State{

private String code;
private String state;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}


}

In the following code, you will find the StateDAOImpl which the implementation of the StateDAO. There are two advantages of using spring DAOs

  1. Datasource is injected and it is reusable across all the custom DAOs
  2. Proprietary RDBMS or JDBC specific SQLException translation to generic spring based exceptions.

The second advantage is very important because it allows to change the database any time.

package au.com.ojitha.blogspot.spring3.part7;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.jdbc.object.MappingSqlQuery;
import org.springframework.stereotype.Repository;

@Repository("stateDAO")
public class StateDAOImpl implements StateDAO<State> {

private DataSource datasource;


public DataSource getDatasource() {
return datasource;
}

@Resource(name="dataSource")
public void setDatasource(DataSource datasource) {
this.datasource = datasource;
}

public String create(State instance) {
// TODO Auto-generated method stub
return null;
}

public void update(State t) {
// TODO Auto-generated method stub

}

public State findByPrimaryKey(String id) {
// TODO Auto-generated method stub
return null;
}

public List<State> findAll() {

return (new SelectAll()).execute();
}

public void delete(State t) {
// TODO Auto-generated method stub

}

public State getStateCode(String state) {
// TODO Auto-generated method stub
return null;
}

private class SelectAll extends MappingSqlQuery<State>{

SelectAll(){
super(datasource, "SELECT CODE, STATE FROM STATE");
}

@Override
protected State mapRow(ResultSet rs, int rowNum) throws SQLException {
State state = new State();
state.setCode(rs.getString("code"));
state.setState(rs.getString("state"));
return state;
}

}
}

In the above code, only the findAll() method has been implemented (for simplicity). Instead of using JDBCTemplate, I’ve used MappingSqlQuery.

Here the spring configuration file, app-context.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<description>Example configuration to get you started.</description>

<context:component-scan base-package="au.com.ojitha.blogspot.spring3.part7" />
<context:annotation-config></context:annotation-config>

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>${jdbc.driverClassName}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
<context:property-placeholder location="classpath:META-INF/spring/jdbc.properties"/>
</beans>

The jdbc.properties contains the values for the above place holders such as jdbc.driverClassName

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/payroll
jdbc.username=ojitha
jdbc.password=ojitha

We are ready to run the example with Client application as shown in the following code

package au.com.ojitha.blogspot.spring3.part7;

import java.util.List;

import org.springframework.context.support.GenericXmlApplicationContext;

public class Client {

/**
* @param args
*/
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:META-INF/spring/app-context.xml");
ctx.refresh();
StateDAO<State> stateDAO = ctx.getBean("stateDAO", StateDAO.class);
List<State> states =stateDAO.findAll();
for (State state : states) {
System.out.println("code: "+state.getCode()+ ", State: "+state.getState());
}

}

}

Here the pom.xml which configure the MySQL connector and Spring-jdbc

<?xml version="1.0" encoding="UTF-8"?>
<project 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"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.spring</groupId>
<artifactId>spring-utility</artifactId>
<version>1.0.0.CI-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Utility</name>
<url>http://www.springframework.org</url>
<description>
<![CDATA[
This project is a minimal jar utility with Spring configuration.
]]>
</description>
<properties>
<maven.test.failure.ignore>true</maven.test.failure.ignore>
<spring.framework.version>3.2.2.RELEASE</spring.framework.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.framework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.24</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
</dependency>


</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>

</plugins>
</build>
</project>

The next step is how to test this code. If you see the above pom.xml, I’ve already add the HSQL plugin for embedded databases.

package au.com.ojitha.blogspot.spring3.part7;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class StateDAOImplTest {

@Autowired
StateDAO stateDao;

@Test
public void testFindAll() {
assertEquals(2, this.stateDao.findAll().size());

}

}

This is just a simple test, as sated in the StateDAOImplTest-context.xml file, HSQL embedded database used with DDL(schema.sql) and DML (data.sql)

 

<?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:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<description>Example configuration to get you started.</description>

<context:component-scan base-package="au.com.ojitha.blogspot.spring3.part7" />
<context:annotation-config></context:annotation-config>

<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="/au/com/ojitha/blogspot/spring3/part7/schema.sql" />
<jdbc:script location="/au/com/ojitha/blogspot/spring3/part7/data.sql" />
</jdbc:embedded-database>

</beans>

As shown in the following schema.sql DDL script, state table is created, because at this time we are only testing StateDAOImpl.java,

CREATE TABLE state (
CODE CHAR(3) NOT NULL,
STATE VARCHAR(30),
PRIMARY KEY (CODE)
);

As well, DML script that is data.sql insert two records to the sate database

insert into state values ('ACT', 'Capital');
insert into state values ('NSW', 'New South Wales');

 

You can download the source code for this blog from the GitHub.

Saturday, April 20, 2013

How To: GitHub projects in Spring Tool Suite

The first step is sign up in the GitHub and create a  new project. For example I’ve created a new project Spring3part7 in the GitHub. Before add the projects you need to configure STS for GitHub access. For example, you need to add configuration as shown in the following picture

image

Git local repository also important

image

Now you are ready to pull the project from the GitHub, in the STS import menu select the following

image

Now type the project name and click the ‘Search’ as shown in the following. However, when you select the found project click ‘Finish’ nothing will change in the STS interface.

image

Now you are going to create real project. Here I am going to create simple utility project.

image

This template project need to be created inside the imported GitHub project

image

You have to give the same project name of the GitHub project as shown in the following project

image

Now your project is ready to push. Before that you need to add ignore flag to all the folders and files except pom.xm , src and test.

image

Navigator view is the easiest for me

image

Now you can ‘commit’ as shown in the following

image

For this initial commit you can click the ‘Commit and Push’. In the following screen press ‘OK’ to push.

image

Now you are ready for your journey.