Thursday, 7 May 2009

Persistence in Spring

Last week I read Spring in Action by Craig Walls.

It was very good book and I found it very informative.

I would like to share few quotations from the book, which gives generic idea about Persistance in Spring.

Spring comes with a family of data access frameworks that integrate with a variety of data access technologies. Whether you are persisting your data via direct JDBC, iBATIS, or an object relational mapping (ORM) framework like Hibernate, Spring removes the tedium of data access from your persistence code. Instead, you can lean on Spring to handle the low-level data access work for you so that you can turn your attention to managing your application’s data.

Spring supports persistence mechanisms like JDBC, Hibernate, the Java Persistence API (JPA), iBATIS etc.

DAO stands for data access object, which perfectly describes a DAO’s role in an application. DAOs exist to provide a means to read and write data to the database.

They should expose this functionality through an interface by which the rest of the application will access them. This has a couple of advantages. First, it makes your service objects easily testable since they are not coupled to a specific data access implementation.

In addition, the data access tier is accessed in a persistence technology–agnostic manner. That is, the chosen persistence approach is isolated to the DAO while only the relevant data access methods are exposed through the interface. This makes for a flexible application design and allows the chosen persistence framework to be swapped out with minimal impact to the rest of the application. If the implementation details of the data access tier were to leak into other parts of the application, the entire application would become coupled with the data access
tier, leading to a rigid application design.

One way Spring helps you insulate your data access tier from the rest of your application is by providing you with a consistent exception hierarchy that is used across all of its DAO frameworks.

In JDBC , you can’t do anything with JDBC without being forced to catch java.sql.SQLException. SQLException is treated as a “one size
fits all” exception for problems related to data access. Rather than have a different exception type for each possible problem, SQLException is sthe exception that’s thrown for all data access problems.

Even so, Hibernate’s exceptions are specific to Hibernate. As stated before, we’d like to isolate the specifics of the persistence mechanism to the data access layer. If Hibernate-specific exceptions are being thrown then the fact that we’re dealing with Hibernate will leak into the rest of the application. Either that, or you’ll be forced to catch persistence platform exceptions and rethrow them as platform-agnostic exceptions.

On one hand, JDBC’s exception hierarchy is too generic—in fact, it’s not much of a hierarchy at all. On the other hand, Hibernate’s exception hierarchy is proprietary to Hibernate. What we need is a hierarchy of data access exceptions that are descriptive but not directly associated with a specific persistence framework.

Spring’s persistence platform agnostic exceptions :
Spring JDBC provides a hierarchy of data access exceptions that solve both problems. In contrast to JDBC, Spring provides several data access exceptions, each descriptive of the problem.

Even though Spring’s exception hierarchy is far more rich than JDBC’s simple SQLException, it isn’t associated with any particular persistence solution. This means that you can count on Spring to throw a consistent set of exceptions, regardless of which persistence provider you choose. This helps to keep your persistence choice confined to the data access layer.

Spring promotes the use of unchecked exceptions. This leaves the decision of whether to catch an exception in the developer’s hands. To take advantage of Spring’s data access exceptions, you must use one of Spring’s supported data access templates.

Spring applies Template method Pattern to data access.

It separates the fixed and variable parts of the data access process into two distinct classes: templates and callbacks. Templates manage the fixed part (controlling transactions, managing resources, and handling exceptions)of the process while your custom data access code (creating statements, binding parameters, and marshaling result sets) is handled in the callbacks.

Spring comes with several templates to choose from, depending on your persistence platform choice. If you’re using straight JDBC then you’ll want to use JdbcTemplate. But if you favor one of the object-relational mapping frameworks then perhaps HibernateTemplate or JpaTemplate is more suitable. Direct wiring of the templates is fine, but Spring also provides a set of convenient DAO base classes that can manage the template for you.

The data access templates are not all there is to Spring’s data access framework. Each template also provides convenience methods that simplify data access without the need to create an explicit callback implementation. Furthermore, on top of the template-callback design, Spring provides DAO support classes that are meant to be subclassed by your own DAO classes.

When writing your application DAO implementation, you can subclass a DAO support class and call a template retrieval method to have direct access to the underlying data access template. For example, if your applicationDAO subclasses JdbcDaoSupport then you only need to call getJdbcTemplate() to get a JdbcTemplate to work with.

Just as Spring provides several data access template implementations, it also provides several DAO support classes—one for each template.

Spring’s persistence support options will depend on a data source. So, let us know how to configure Spring with a data source for the DAOs to access the database.

Configuring a data source

Regardless of which form of Spring DAO support you use, you’ll likely need to configure a reference to a data source. Spring offers several options for configuring data source beans in your Spring application, including:
1. Data sources that are defined by a JDBC driver
2. Data sources that are looked up by JNDI
3. Data sources that pool connections

1. Let us look at using JNDI data sources :

Spring applications will quite often be deployed to run within a JEE application server such as WebSphere, JBoss, or even a web container like Tomcat. These servers allow you to configure data sources to be retrieved via JNDI. The benefit of configuring data sources in this way is that they can be managed completely external to the application, leaving the application to simply ask for a data source when it’s ready to access the database. Moreover, data sources managed in an application server are often pooled for greater performance and can be hotswapped
by system administrators.

With Spring, we can configure a reference to a data source that is kept in JNDI and wire it into the classes that need it as if it were just another Spring bean. Spring’s JndiObjectFactoryBean makes it possible to retrieve any object, including data sources, from JNDI and make it available as a Spring bean.

How does JndiObjectFactoryBean retrieve a data source from JNDI:


<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="/jdbc/SampleDatasource" />
<property name="resourceRef" value="true" />
</bean>


The jndiName attribute is used to specify the name of the resource in JNDI. If only the jndiName property is set then the data source will be looked up as is. But if the application is running within a Java application server then you’ll want to set the resourceRef property to true.

When resourceRef is true, the value of jndiName will be prepended with java:comp/env/ to retrieve the data source as a Java resource from the application server’s JNDI directory. Consequently, the actual name used will be java:comp/env/jdbc/SampleDatasource.

2 Using a pooled data source :

Configuring a BasicDataSource bean is like


<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/test"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
</bean>


The first four properties are elemental to configuring a BasicDataSource. The driverClassName property specifies the fully qualified name of the JDBC driver class. Here we’ve configured it with the JDBC driver for the Hypersonic database. The url property is where we set the complete JDBC URL for the database. Finally, the username and password properties are used to authenticate when you’re connecting to the database. Those four basic properties define connection information for BasicData- Source. In addition, several properties can be used to configure the data source pool itself.

3. JDBC driver-based data source

The simplest data source you can configure in Spring is one that is defined through a JDBC driver. Spring offers two such data source classes to choose from (both in the org.springframework.jdbc.datasource package):

-> DriverManagerDataSource—Returns a new connection every time that a connection is requested. Unlike DBCP’s BasicDataSource, the connections
provided by DriverManagerDataSource are not pooled.

-> SingleConnectionDataSource—Returns the same connection every time that a connection is requested. Although SingleConnectionDataSource
isn’t exactly a pooled data source, you can think of it as a data source with a pool of exactly one connection.

Configuring either of these data sources is similar to how we configured DBCP’s BasicDataSource as shown above. The only difference is that since neither DriverManagerDataSource nor Single-ConnectionDataSource provides a connection pool, there are no pool configuration
properties to set.

Although SingleConnectionDataSource and DriverManagerDataSource are great for small applications and running in development, you should seriously consider the implications of using either in a production application. Because SingleConnectionDataSource has one and only one database connection to work with, it doesn’t work well in a multithreaded application. At the same time, even though DriverManagerDataSource is capable of supporting multiple threads, it incurs a performance cost for creating a new connection each time a connection is requested. Because of these limitations, using pooled data sources strongly recommend.

Hope it will be useful...

5 comments:

Prashant Jalasutram said...

Nice Explanation about JDBC - Spring integration Sneha.

Regards
Prashant

jishnu said...

Hai sneha,

Can you publish any tutorials about spring integration with iBatis.Including any tutorials for 'how to store and retrieve array data type using iBatis.

jishnu said...

Please help me,

Which one is the better for web application project with IBatis or Hibernate.

I am going to develop new project.Can you explain which technology is better for persistence part with iBatis or Hibernate

Freekeswar said...

@jishnu

I think Hibernate will be better.

regards,
Eswar
VaanNila

thiruvas said...

hi sneha,
It's very nice expalation
Thanks&Regards
TIJB