Professional Java Development with the Spring Framework

A data source declaration is a critical part of the transaction infrastructure. Traditionally this is done in J2EE via a JNDI lookup of a javax.sql.DataSource object. The DataSource is pre-configured by the server administrator and enabled to support JTA transactions if necessary. If you are running outside of a J2EE environment, then the data source configuration is up to the application developer and is typically done via some kind of factory object that obtains a java.sql.Connection through the java. sql.DriverManager interface. This leaves us with two very different and incompatible approaches for data source configuration.

Spring provides a solution for this problem by always using a javax.sql.DataSource for any framework code accessing a database. To avoid the factory/lookup problem, Spring's IoC framework allows us to easily configure a data source that will be provided to the application without any messy lookup code. The following examples show configurations for local configurations as well as for J2EE configurations obtained via JNDI. The application program is not aware of the type of data source used. All thatis needed for your program to access the database is a reference to the common interface javax.sql. DataSource.

Local Unpooled

For code running outside a J2EE environment, Spring provides a couple of DataSource implementations that don't rely on any pre-configured server resources. Instead, these implementations use the DriverManager internally to present the connection wrapped in a javax.sql.DataSource interface.

Important 

These implementations are primarily intended to be used for unit and integration testing and they are not intended for production use. We recommend using one of the solutions providing connection pooling mentioned in the following section for any production use.

The first data source we will look at is the DriverManagerDataSource. We need to supply the name of the JDBC driver class, the connection URL, as well as a username and password combination that lets us connect to the database. Here is an example of this configuration:

<bean > <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:hsql://localhost:9001</value> </property> <property name="username"><value>sa</value></property> <property name="password"><value></value></property> </bean>

DriverManagerDataSource does not provide any pooling of the connection resources. It does provide a new connection each time the getConnection method is called. This is not ideal and Spring provides an implementation named SingleConnectionDataSource that will keep the connection open for multiple uses:

<bean destroy-method="destroy"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:hsql://localhost:9001</value> </property> <property name="username"><value>sa</value></property> <property name="password"><value></value></property> </bean>

As long as this data source is accessed via Spring's JdbcTemplate or DataSourceUtils getConnection and closeConnectionIfNecessary methods, then the connection will be kept open. If you use legacy code that accesses the connection directly and calls the connection's close method, then you must set the supressClose property to true for the SingleConnectionDataSource:

<property name="supressClose"><value>true</value></property>

It is important to note that you don't want to leave this connection open forever. In order for the connection to really be closed, you should invoke the destroy method after all processing is done. Also, this DataSource is not threadsafe and it is best to get a new instance for each use via a method-injection lookup-method. See Chapter 2 for more on this configuration option.

Local Pooled

Spring does not provide a connection pool implementation because several open source projects already do so. We recommend using a data source configuration based on the pool implementation from the Apache Commons DBCP or SourceForge c3P0 projects. Here is a sample configuration using the BasicDataSource from Apache Commons DBCP. Aside from usage in production, this connection pool is quite lightweight and is also quite easy to use even for testing. There are no common scenarios where you would be at a disadvantage in using it instead of DriverManagerDataSource or SingleConnectionDataSource, while there are some advantages, because using a pooling

<bean destroy-method="close"> <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>

JNDI

Most application servers include a connection pool implementation and they also let you configure data sources that can be bound to the server's JTA implementation. This enables you to use Spring's JTA support for the transaction framework that we already covered earlier in this chapter. We recommend using the connection pooling that is included with your application server or a configuration based on one of the open source implementations mentioned previously.

The connection pooling implementations provided by an application server allow you to bind a data source using the pool to a JNDI name. This is the preferred way to obtain the data source in a J2EE environment. To avoid having to code the JNDI lookup, you should use Spring's JndiObjectFactoryBean to obtain the reference to the DataSource object. Here is a sample configuration using the JNDI lookup name of java:comp/env/jdbc/mydb:

<bean > <property name="jndiName"><value>java:comp/env/jdbc/mydb</value></property> </bean>

The J2EE server appends a java:comp/env/ prefix to the JNDI name and you can either specify the full name as we did in the previous example or you can set the resourceRef property of JndiObjectFactoryBean to true. Here is an example of this style:

<bean > <property name="jndiName"><value>jdbc/mydb</value></property> <property name="resourceRef"><value>true</value></property> </bean>

Choosing Between Local and JNDI DataSource

Should you always use a JNDI DataSource that is provided by your application server or are there advantages to using a locally defined pooled DataSource?

A DataSource implementation that is provided by your application server vendor will always be better supported by this vendor. This is an important consideration if you are using their paid support offering. Additionally, this type of DataSource can be shared by several applications accessing the same database. This can be important if you must limit the number of open connections for the database. Most databases have a configurable limit for how many connections can be open at a time. Even if the connection is not actively used, it is still open while it is in the pool, and it uses resources on the database side.

The locally defined DataSource makes it much easier to deploy your application. There isn't any configuration necessary on the application server side. The entire configuration is part of your application. This is a considerable advantage if your application is going to be deployed to many different application servers. This is especially true if you also have full and exclusive control over the database your application accesses.

As you can see, both solutions have their advantages and you will have to weigh the advantages of the two solutions based on your requirements and other limiting factors.

Important 

Spring completely abstracts this choice away from application code. It is reduced to a configuration issue. Spring enables a consistent, simple programming model and allows you additional options.

Категории