Any non trivial enterprise application usually have a persistence mechanism and usually it’s a SQL compliant database. Please note that Spring does not provide any native support for database access. Spring does not provides any SQL like language to connect to database. What Spring provides is integration to various data access framework which includes
Spring provides the following features to handle the database:
Let's create a Student class and persist it.
Student.java
public class Student {
protected String name;
//Getters and setters
Let's use ((Hypersonic)) database to persist the data. Bring the hsqldb.jar in the application path and start it as mentioned in ((Hypersonic)).
SQL for creating Student
CREATE TABLE STUDENT ( NAME VARCHAR )
Let's first look into the classic way of persisting the data.
Student student = new Student();
student.setName("Amitabh");
try{
Class.forName("org.hsqldb.jdbcDriver");
}catch(ClassNotFoundException cfe){
System.out.println("Driver not found");
System.exit(0);
}
Connection conn = null;
PreparedStatement stmt = null;
try{
conn = DriverManager.getConnection ("jdbc:hsqldb:hsql://localhost","sa","");
stmt = conn.prepareStatement ("insert into STUDENT (name) values (?) ");
stmt.setString(1, student.getName());
stmt.execute();
}catch(SQLException se){
System.out.println("Problem with data insert");
} finally{
try{
if(stmt != null) {stmt.close();}
if(conn != null) {conn.close();}
}catch(SQLException se) {}
Look how much verbose is the code. The program in statement is:
Note that apart from the step of specifying the statement, rest all is boiler plate code which is repeated endlessly.Now let's see how Spring handles this situation. Before we move further let's look into Spring DAO philosophy. Spring promotes a pattern called Data Access Object(DAO) pattern, where Spring promotes interface based approach. This leads to flexibility in the programming model as it facilitates change of concrete implementation with ease. Let's write the interface
StudentDao
public interface StudentDao {
public void saveStudent(Student student); }
And if we are dealing with JDBC based interaction to database, the implementation class will look like
public class StudentJdbcDao implements StudentDao{
public void saveStudent(Student student) {
//Here we have to provide the implementation.
//We can pull our JDBC interaction code here
//but we do not achieve much with this apart from an indirection because of interface.
}
}
Let's take a step back and understand how Spring handles this kind of situation. Spring adopts a template based approach. The role of template is to wrap up all the boiler plate code and provide interfaces so that the developers can focus on business specific code.Spring handles the data access using templates and callbacks.Any data access technology is used it has a fixed part(boiler plate code) and a programmer defined part. The fixed part like opening closing connection is handled by template and the variable part like how to handle the result is handled by callbacks.
Spring comes with several data access template for different persistence mechanism:
At the moment we are looking into JDBC way of interacting to database so Let's see how templates related to JDBC come to action. In this regard we will use JdbcTemplate first.JdbcTemplate class simplifies working with JDBC. It automatically handles resource management, exception handling and transaction management.It is a thread safe class so you can use a single instance that many classes can use. Underlying Connection can also be accessed.So now our implementation class for JdbcDao looks like
StudentJdbcDao.java
public class StudentJdbcDao implements StudentDao{
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
public void saveStudent(Student student) {
jdbcTemplate.update
("insert into STUDENT (name) values (?)",new Object[] {student.getName()} );
}
}
Now the question is how StudentJdbcDao gets the jdbcTemplate. In true Spring fashion let's wire the relationship.
In context.xml
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource“
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
dataSource is the bean in which we provide all the database connection properties. Than we inject dataSource in jdbcTemplate and than let's inject jdbcTemplate in StudentJdbcDao.
<bean id="studentDao" class="StudentJdbcDao">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
Note that we have given the id as studentDao but the actual class is StudentJdbcDao(Use full package name). We can now access our dao in calling code:
Student student = new Student();
student.setName("AmitabhDao");
StudentDao studentDao = (StudentDao)appContext.getBean("studentDao");
studentDao.saveStudent(student);
The jars required for this are:
The source files and configuration file can be downloaded from attachment.
It's possible that we might have many dao classes to handle different database interactions. So that will result in writing a lot of code to handle jdbcTemplate. To solve this Spring comes with a convenient class JdbcDaoSupport which gives access to JdbcTemplate
public class StudentJdbcDao extends JdbcDaoSupport implements StudentDao {
public void saveStudent(Student student) {
this.getJdbcTemplate().update
("insert into STUDENT (name) values (?)",
new Object[] {student.getName()} );
}
}
The configuration code in context.xml remains same.
Configuring Data Sources
Spring provides a number of ways to configure data source.
We saw earlier how to handle the connection using connection properties when we are working with JDBC directly. Spring provides two basic JDBC driver based datasource
<bean id =“datasource” class=“org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name="driverClassName“ value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
For JNDI datasource, the datasource is feteched using JNDI lookup
<bean id ="datasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name=“jndiName” value=/jdbc/ds”/>
<property name=“resourceRef” value=“true”/>
</bean>
With jee namespace, it can be written more succinctly
<jee:jndi-lookup id=“datasource” jndi-name=“jdbc/ds” resource-ref=“true” />
Spring provides the capability to pool the datasource in the application itself using Jakarta’s Commons Database Connection Pools (DBCP)
<bean id ="datasource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name=“initialSize” value=“5”/>
<property name=“maxActive” value=“10”/>
</bean>
JDBCTemplate
Spring provides three types of template class to work with JDBC
public class StudentJdbcDao implements StudentDao {
protected NamedParameterJdbcTemplate namedJdbcTemplate;
//Method to inject NamedParameterJdbcTemplate
public void setNamedJdbcTemplate (NamedParameterJdbcTemplate namedJdbcTemplate) {
this.namedJdbcTemplate = namedJdbcTemplate;
}
public void saveStudent(Student student) {
Map parameters = new HashMap();
parameters.put("name",student.getName());
namedJdbcTemplate.update
("insert into STUDENT (name) values (:name)",
parameters);
}
...
}
In configuration XML
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
Note that the datasource is injected as constructor argument.
In case of SimpleJdbcTemplate the Dao class looks like:
protected SimpleJdbcTemplate simpleJdbcTemplate;
//Setter method for SimpleJdbcTemplate
...
public void saveStudent(Student student) {
//Note how the arguments are passed. It uses varargs feature.
simpleJdbcTemplate.update
("insert into STUDENT (name,percentage) values (?,?)",
student.getName(),student.getPercentage());
Configuration XML
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
Fetching Collections
Now let's look how we can fetch the collection from database. We will use the SimpleJdbcTemplate to do that
public List<Student> getAllStudents() {
return simpleJdbcTemplate.query
("Select name as Name from Student",
new ParameterizedRowMapper<Student>(){
public Student mapRow(ResultSet rs,int rowNum)
throws SQLException {
Student student = new Student();
student.setName(rs.getString("Name"));
return student;
}
}
);
}
Note how anonymous inner class ParameterizedRowMapper<Student> is registered as a parameter to the query method. Now to understand that again think in terms of moving part and fixed part. The moving part is the query which is passed as first argument. The fixed part is the boiler plate code which handles opening and closing connection, making and executing statement and iterating through the result. Again the moving part is how to handle each iteration. This is provided by the mapRow method. The mapRow method is called as a callback for every iteration.
Transactions
Spring supports the following way of defining transaction
Spring has no capability to manage transactions directly. The transaction management is delegated to platform specific transaction implementation provided by either JTA or the persistence mechanism.Spring supports wide variety of transaction manager.
Plain JDBC transaction is handled by DataSourceTransactionManager.DataSourceTransactionManager manages the transaction automatically by calling commit on success and in the case of failure calling the rollback.Define the transaction manager and transaction template
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" >
<property name="transactionManager" ref="transactionManager"/>
</bean>
Controlling transaction programmatically
public void saveUser(final User user) {
transactionTemplate.execute(
new TransactionCallback(){
public Object doInTransaction(TransactionStatus ts){
try{
userDao.saveUser(user);
}catch(Exception ex){
ts.setRollbackOnly();
}
return null;
});}
Spring defines declarative transaction using attributes:
Annotation Driven Transaction
With annotations introduced in Java 5+, handling transaction has been made very easy. Add the transaction manager by registering the transaction manager in configuration XML. This also has been made easy by using tx namespace
<tx:annotation-driven/>
Add the annotation
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class UserListService {
@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void insertUser(final User user) {
userDao.saveUser(user);
}
The annotation drives the behavior for all methods in the class. The behavior for individual method can be overridden by putting annotation on individual method.
Comments
excellent
it is very nice,i read many tutorials about spring,,but i couldnot understand it
but in your tutorial it is very simple and understandable
thank you ..go ahead :)
Good job Lalit
Good post
Add new comment