Chapter 3. Accessing Data with Spring

Data access or persistence is a major technical feature of data-driven applications. This is a critical area where careful design and expertise is required. Modern enterprise systems use a wide variety of data storage mechanisms ranging from traditional relational databases such as Oracle, SQL Server, and Sybase to more flexible, schema-less NoSQL databases such as MongoDB, Cassandra, and Couchbase. Spring Framework provides comprehensive support for data persistence in multiple flavors of mechanism, ranging from convenient template components to smart abstractions over popular ORM (Object Relational Mapping) tools and libraries, making them much easier to use. Spring's data access support is another great reason for choosing it for developing Java applications.

Spring Framework offers the following primary approaches for data persistence mechanisms for developers to choose from:

  • Spring JDBC
  • ORM Data Access
  • Spring Data

Furthermore, Spring standardizes the preceding approaches under a unified DAO (Data Access Object) notation called @Repository.

Another compelling reason for using Spring is its first class transaction support. Spring provides consistent transaction management, abstracting different transaction APIs such as JTA, JDBC, JPA, Hibernate, JDO, and other container-specific transaction implementations.

In order to make development and prototyping easier, Spring provides embedded database support, smart abstractions (DataSource), and excellent test integration. This chapter explores various data access mechanisms provided by Spring Framework and its comprehensive support for transaction management in both standalone and web environments, with relevant examples.

Note

Why use Spring Data Access when we have JDBC?

JDBC (Java Database Connectivity), the Java Standard Edition API for data connectivity from Java to relational databases, is a very a low-level framework. Data access via JDBC is often cumbersome; the boiler-plate code the developer needs to write makes the code error-prone. Moreover, JDBC exception handling is not sufficient for most use cases; there exists a real need for simplified but extensive and configurable exception handling for data access. Spring JDBC encapsulates the often repeating code, simplifying the developer code tremendously, and lets him/her focus directly on his business logic. Spring Data Access components abstract the technical details including the lookup and management of persistence resources such as connections, statements, and resultsets, and accept the specific SQL statements and relevant parameters to perform the operation. Spring Data Access components use the same JDBC API under the hood, while exposing simplified, straightforward interfaces for the client's use. This approach makes for a much cleaner and hence maintainable data access layer for Spring applications.

Configuring DataSource

The first step to connect to a database from any Java application is to obtain a connection object specified by JDBC. DataSource, a part of Java SE, is a generalized factory of java.sql.Connection objects that represents the physical connection to the database and is the preferred means of producing a connection. DataSource handles transaction management, connection lookup, and pooling functionalities, relieving the developer of those infrastructural issues.

DataSource objects are often implemented by database driver vendors and typically looked up via JNDI. Application servers and Servlet engines provide their own implementations of DataSource (and) or connectors to DataSource objects provided by the database vendor. Typically configured inside XML-based server descriptor files, server-supplied DataSource objects generally provide built-in connection pooling and transaction support. As a developer, you just configure your data sources inside the server configuration files declaratively in XML and look them up from your application via JNDI.

In a Spring application, you configure your DataSource reference as a Spring bean, and inject it as a dependency into your DAOs or other persistence resources. The Spring <jee:jndi-lookup/> tag (of http://www.springframework.org/schema/jee namespace) allows you to look up and construct JNDI resources easily, including a DataSource object defined from inside an application server. For applications deployed in a J2EE application server, a JNDI DataSource object provided by the container is recommended.

<jee:jndi-lookup id="taskifyDS" jndi-name="java:jboss/datasources/taskify"/>

For standalone applications, you need to create your own DataSource implementation or use third-party implementations such as Apache Commons DBCP, C3P0, or BoneCP. The following is a sample DataSource configuration using Apache Commons DBCP2. It provides configurable connection pooling features too.

<bean id="taskifyDS" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${driverClassName}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}" />
    <property name="password" value="${password}" />
    <property name="initialSize" value="3" />
    <property name="maxTotal" value="50" />
    ...
</bean>

Make sure you add the corresponding dependency to your DataSource implementation in your build file. The following is for DBCP2:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.1.1</version>
</dependency>

Spring provides DriverManagerDataSource, a simple implementation of DataSource, which is only meant for testing and development purposes, not for production use. Note that it does not provide connection pooling. Here is how you configure it in your application.

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

It can also be configured using the Java-based configuration, as shown in the following code:

@Bean
DataSource getDatasource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource(pgDsProps.getProperty("url"));
    dataSource.setDriverClassName( pgDsProps.getProperty("driverClassName"));
    dataSource.setUsername(pgDsProps.getProperty("username"));
    dataSource.setPassword(pgDsProps.getProperty("password"));
    return dataSource;
}

Note

Never use DriverManagerDataSource on production environments. Use third-party data sources such as DBCP, C3P0, and BoneCP for standalone applications, and JNDI DataSource provided by the container, for the J2EE container instead. They are more reliable and provide efficient connection pooling functionality off the shelf.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset