How to configure Hibernate in Spring.


The objective of the tutorial is to understand how the DB can be configured in Spring using Hibernate.
To start with download:
1) spring jars
2) hibernate jars
3) mysql driver

Following is the list of jars I used.

1) create a Db in mysql with name “reco_engine”;
2) Create a table User and add some columns to it.
3) Insert some records into the table using mysql..

<?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">

<bean id="hibernateDao" class="HibernateAccessDao">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/reco_engine"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>

<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>Users.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>hibernate.dialect=org.hibernate.dialect.HSQLDialect</value>
</property>
</bean>

<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
</bean>
</beans>

The bean “datasource” is used to configure the properties of the DB.
The bean “mySessionFactory” is used to maintain the session of hibernate. This is taken care by the spring container now.
The property “mappingResources” takes the list of hbm files which will be mapped to this session. Also the datasource property is set in this bean.

The bean hibernateTemplate is the one used to interact with the DB. The Spring application context will manage its lifecycle, initializing and shutting down the factory as part of the application. LocalSessionFactoryBean is the preferred way of obtaining a reference to a specific Hibernate SessionFactory, at least in a non-EJB environment.

The bean “hibernateDao” is the java class and the hibernateTemplate property is set.

The Users table has to be mapped in Hibernate. To map it , Users.java and Users.hbm.xml need to be created . I have used the Hibernate plugin for eclipse provided by JBoss to generate the files automatically. http://jboss.org/tools

The files will be as follows:


public class Users  implements java.io.Serializable {


    // Fields    

     private int id;
     private String firstname;
     private String lastname;
    
    // Constructors

    /** default constructor */
    public Users() {
    }

	/** minimal constructor */
    public Users(int id) {
        this.id = id;
    }
    
  
    // Property accessors

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

      public String getFirstname() {
        return this.firstname;
    }
    
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return this.lastname;
    }
    
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
}

The Users.hbm.xml


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jun 3, 2010 9:15:59 PM by Hibernate Tools 3.1.0.beta4 -->
<hibernate-mapping>
    <class name="Users" table="users" catalog="reco_engine">
        <id name="id" type="int">
            <column name="id" />
            <generator class="assigned" />
        </id>
        <property name="firstname" type="string">
            <column name="firstname" length="45" />
        </property>
        <property name="lastname" type="string">
            <column name="lastname" length="45" />
        </property>
        <property name="designation" type="string">
            <column name="designation" length="45" />
        </property>
        <property name="department" type="string">
            <column name="department" length="45" />
        </property>
    </class>
</hibernate-mapping>

The Dao class to interact with the database:


public class HibernateAccessDao {

	HibernateTemplate hibernateTemplate;

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ApplicationContext context =   new ClassPathXmlApplicationContext("spring.xml");
		HibernateAccessDao dao =(HibernateAccessDao) context.getBean("hibernateDao");
		dao.getRecords();
	}
	
// This method retrieves the record with id =1
	private void getRecords(){
		
		Session session = hibernateTemplate.getSessionFactory().openSession();
		Users user = (Users) session.load(Users.class, 1);
		System.out.println(user.getFirstname());
	}

}

The session.load(User.class,1) will load the record of the user with id =1

Advertisements

How to acheive concurrency in Hiberante ?


Consider a scenario in which multiple applications are accessing same database. It is likely that is a data or row is fetched by an application1 and
later on by application2 and application2 makes an update in DB and when application1 makes update then if finds that the old data is lost and not sure what
to do.
To maintain high concurrency and high scalability hibernate allows the concept of versioning.Version checking uses version numbers, or timestamps, to detect conflicting updates (and to prevent lost updates). Hibernate provides for three possible approaches to writing application
code that uses optimistic concurrency.
1) Application version checking: each interaction with the database occurs in a new Session and the developer is responsible for reloading all persistent instances from the database before manipulating them. This approach forces the application to carry out its own version checking to ensure conversation transaction isolation.
This approach is the least efficient in terms of database access.
// foo is an instance loaded by a previous Session
session = factory.openSession();
Transaction t = session.beginTransaction();
int oldVersion = foo.getVersion();
session.load( foo, foo.getKey() ); // load the current state
if ( oldVersion != foo.getVersion() ) throw new StaleObjectStateException();
foo.setProperty("bar");
t.commit();
session.close();

The version property is mapped using <version>, and Hibernate will automatically increment it during flush if the entity is dirty.
Clearly, manual version checking is only feasible in very trivial circumstances and not practical for most applications.

2) Extended session and automatic versioning : A single Session instance and its persistent instances are used for the whole conversation, known as session-per-conversation. Hibernate checks instance versions at flush time, throwing an exception if concurrent modification is detected. It’s up to the developer to catch and handle this exception.
The Session is disconnected from any underlying JDBC connection when waiting for user interaction. This approach is the most efficient in terms of database access. The application need not concern itself with version checking or with reattaching detached instances, nor does it have to reload instances in every database transaction.

// foo is an instance loaded earlier by the old session
Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction
foo.setProperty("bar");
session.flush(); // Only for last transaction in conversation
t.commit(); // Also return JDBC connection
session.close(); // Only for last transaction in conversation

3)  Detached objects and automatic versioning: Each interaction with the persistent store occurs in a new Session. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another Session and then reattaches them using Session.update(), Session.saveOrUpdate(), or Session.merge().
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
Transaction t = session.beginTransaction();
session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded already
t.commit();
session.close();

Again, Hibernate will check instance versions during flush, throwing an exception if conflicting updates occurred.

4) Customizing automatic versioning
You may disable Hibernate’s automatic version increment for particular properties and collections by setting the optimistic-lock mapping attribute to false. Hibernate will then no longer increment versions if the property is dirty.
Legacy database schemas are often static and can’t be modified. Or, other applications might also access the same database and don’t know how to handle version numbers or even timestamps. In both cases, versioning can’t rely on a particular column in a table. To force a version check without a version or timestamp property mapping, with a comparison of the state of all fields in a row, turn on optimistic-lock=”all” in the <class> mapping
Sometimes concurrent modification can be permitted as long as the changes that have been made don’t overlap. If you set optimistic-lock=”dirty” when mapping the <class>, Hibernate will only compare dirty fields during flush