Spring JDBC Abstract Framework simplifies web database development

Source: Internet
Author: User
Tags abstract error code error handling exception handling implement sql tostring oracle database
web| Data | database I. Introduction

Spring is a lightweight application framework. In many cases, spring can be a good substitute for the traditional services provided by Java EE application servers. Spring is both comprehensive and modular. Based on its layered architecture, it enables developers to flexibly use any part of their own. Spring is made up of many modules, such as IOC containers, AOP,MVC, Persistence, DAO, and remoting. These modules are fairly loosely coupled: some modules are not used at all to require additional modules. In the past, there was no such thing as a spring application: You could choose to build your application with some, most, or all of the components supported by the spring framework.

The JDBC support provided by the spring framework is not tightly coupled with the other spring parts, which is extremely advantageous to the maintainability of the code. This article will show you how to benefit from spring for any application that directly uses JDBC (i.e., using JDBC without some of the O/R mapping framework itself).

   two. Traditional type JDBC

Traditional JDBC has many positive aspects that make it important in the development of many J2SE and Java-EE applications. However, there are some features that make it difficult to use:

· Developers need to deal with a large number of complex tasks and infrastructure, such as a large number of try-catch-finally-try-catch blocks.

· The application requires complex error handling to determine that the connection is properly closed after use, which makes the code verbose, bloated, and repetitive.

· A SqlException exception with a very ambiguous nature is used in JDBC.

· JDBC does not introduce a specific exception subclass hierarchy mechanism.

As with any error, it simply throws a SqlException exception-whether it comes from the JDBC driver or from the database-which makes it difficult for programmers to understand exactly where the error actually occurred. For example, if the SQL object is invalid or has been locked, a SqlException exception is thrown. Debugging such an exception requires a certain amount of time to check the SQL state value and error code. Furthermore, the meaning of the SQL state value and the error code is somewhat different between the various databases.

It turns out that writing JDBC code is not an easy task-there's a lot of repetitive work to do. To illustrate the problem, here is an example of using traditional JDBC to get a list of available tasks from the database.

Package COM.SPRING.JDBC;
Import java.sql.Connection;
Import Java.sql.DriverManager;
Import java.sql.PreparedStatement;
Import Java.sql.ResultSet;
Import java.sql.SQLException;
Import Java.util.Vector;
public class Traditionaljdbc {
Public Vector Gettasksnames () {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Vector task = new vector ();
try {
con = getconnection ();
pstmt = Con.preparestatement ("Select TaskName from Tasks");
rs = Pstmt.executequery ();
while (Rs.next ()) {
Task.add (rs.getstring (1));
}
catch (SQLException e) {
System.out.println (e);
finally {
try {
Rs.close ();
Pstmt.close ();
Con.close ();
catch (SQLException E1) {
SYSTEM.OUT.PRINTLN (E1);
}
}
return task;
}
Private Connection getconnection () throws SQLException {
try {
Drivermanager.registerdriver (New Oracle.jdbc.driver.OracleDriver ());
Return Drivermanager.getconnection ("Jdbc:oracle:thin: @localhost: 1521:orcl",
"Scott", "Tiger");
catch (SQLException Sqle) {
System.out.println (Sqle);
return null;
}
}
public static void Main (string[] args) {
Traditionaljdbc obj = new Traditionaljdbc ();
Vector task = Obj.gettasksnames ();
for (int i = 0; I task.size (); i++) {
System.out.println (Task.elementat (i));
}
}
}


In addition to the actual query database SQL code, the above example requires a large number of routine code. The Getconnection () method has nothing to do with our task, and even the Gettasksnames () method contains only two lines of code that are specific to the current task. All that remains is some common, complex task code.

Many of the positive aspects of JDBC make it still important in many J2SE and Java EE applications. However, as you can see, there are some features that make it more difficult to use than we might imagine. These tedious and sometimes frustrating features of JDBC have led to the emergence of many public available JDBC abstraction frameworks (such as Sqlexecutor and Apache Jakarta Commons dbutils), as well as countless home-grown JDBC application frameworks. A common, available JDBC Abstraction Framework is the JDBC abstraction of the spring framework.

   three. Introduction to Spring JDBC

The JDBC abstraction framework provided by spring consists of four different packages:

· The core package contains JdbcTemplate. This class is one of the base classes-provided and used by the JDBC support of the spring framework.

· The data source package is an important part of implementing unit test data Inventory substitution code. Its drivermanagerdatasource can be used in a similar way that you have been accustomed to JDBC: simply create a new drivermanagerdatasource and invoke the setter method to set the Driverclassname. Url,username and password.

· The package contains classes that describe the RDBMS queries, changes, and stored procedures as thread-safe, reusable objects.

· Support Packages-You can find SqlException translation features and some tool classes from here.

1 Template design mode

Spring JDBC implements the template design pattern, which means that the repetitive, complex tasks part of the code is implemented in the template class. This simplifies the use of JDBC because it handles the creation and release of resources. This helps avoid common errors, such as forgetting to turn off connections. It performs core JDBC workflow tasks, such as statement creation and execution, and allows application code to provide SQL and extract results.

2 Spring JDBC Exception handling

The spring framework specifically emphasizes the issues that are faced in traditional JDBC programming in relation to the following scenarios:

· Spring provides an abstract exception layer that moves tedious and error-prone exception handling from the application code to the framework. The framework is responsible for all exception handling; The application code can focus on using the appropriate SQL extraction results.

· Spring provides an important level of exception classes so that you can use the appropriate SqlException subclasses in your application code.

With the help of an abstract anomaly layer, we have successfully implemented database independence without changing exception handling. For example, if you change your database from PostgreSQL to Oracle, then you don't have to change the exception handling from Oracledataexception to postgresdataexception. Spring can capture application server-specific exceptions and throw a spring data exception.

When handling exceptions, spring checks the metadata availability of a database connection to determine the database product. It uses this knowledge to map SqlException to specific anomalies in its own anomaly hierarchy. Therefore, we do not need to worry about a specific SQL state or error code problem; Spring's data access exception is not JDBC-specific, so your DAO does not have to bind to JDBC because of the exceptions it might throw.

   four. Spring JDBC Example

In the following two listings, we will use the business logic previously implemented with traditional JDBC as an example and demonstrate how easy it is to use the spring JDBC version. First, we start with a simple interface.

Package COM.SPRING.JDBC;
Import java.util.List;
Public interface Tasksdao {
Public List gettasksnames ();
}
Next, we provide an implementation for the Tasksdao interface.

Package COM.SPRING.JDBC;
Import Java.util.Iterator;
Import java.util.List;
Import Java.sql.ResultSet;
Import java.sql.SQLException;
Import Javax.sql.DataSource;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;
Import Org.springframework.jdbc.core.JdbcTemplate;
Import Org.springframework.jdbc.core.RowMapper;
Import Org.springframework.jdbc.core.RowMapperResultReader;
Import Org.springframework.jdbc.core.support.JdbcDaoSupport;

public class Tasksjdbcdao extends Jdbcdaosupport
Implements Tasksdao {

Public List Gettasksnames () {
JdbcTemplate JT = Getjdbctemplate ();
Return Jt.query ("Select TaskName from Tasks",
New Rowmapperresultreader (New Tasksrowmapper ());
}
Class Tasksrowmapper implements RowMapper {
Public Object Maprow (ResultSet rs, int index)
Throws SQLException {
return rs.getstring (1);
}
}
public static void Main (string[] args) throws Exception {
ApplicationContext CTX = new Classpathxmlapplicationcontext ("Springconfig.xml");
DataSource ds = (DataSource) ctx.getbean ("Datasourcedbdirect");
Tasksjdbcdao Taskdao = new Tasksjdbcdao ();

Taskdao.setdatasource (DS);
Iterator Tskiter = Taskdao.gettasksnames (). iterator ();
while (Tskiter.hasnext ()) {
System.out.println (Tskiter.next (). toString ());
}
}
}


In the example above, the common and complex task code has been handed over to the framework. It should also be noted that, with the help of spring JDBC, we use the control inversion (IoC) container to provide a datasource-we just inject it into the Tasksjdbcdao object.

The concept behind control reversal is often expressed as "Don't look for me, let me find you." The IOC handed over some of the tasks to the framework and broke out of the application code. Instead of having your code call a traditional class library, it's an IOC framework that calls your code. Life cycle callbacks that exist in many APIs, such as the Setsessioncontext () method corresponding to the session EJB, demonstrate this approach.

DataSource must be injected into the class (or in its superclass), which is implemented through the Setdatasource () method. All configuration details are away from business logic or client code; This increases the loose coupling of your application and therefore improves the testability and maintainability of the program. As a choice, we can also create a datasource in the Jndi or servlet container, retrieve it programmatically, and then inject it into the DAO object. Here is a sample spring bean configuration file that you can use-springconfig.xml:

<?xml version= "1.0" encoding= "UTF-8"?
! DOCTYPE beans Public "-//spring//dtd bean//en"
"Http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
<bean id= "Datasourcedbdirect"
Class= "Org.springframework.jdbc.datasource.DriverManagerDataSource"
Destroy-method= "Close" >
<property name= "Driverclassname" value= "Oracle.jdbc.driver.OracleDriver"
<property name= "url" value= "Jdbc:oracle:thin: @localhost: 1521:ORCL"/>
<property name= "username" value= "Scott"
<property name= "password" value= "Tiger"
</bean>
</beans>
This file instructs the Spring Bean container to instantiate a Datasourcedbdirect bean-It is created based on the Org.springframework.jdbc.datasource.DriverManagerDataSource class.

1 implementation of a business layer based on spring JDBC

We've seen a simple example of using spring JDBC, in which case it's very little help from the spring beanfactory (Control reversal container). Now, we will go beyond this simple example. Let's explore how to implement business services based on spring JDBC. First, let's create a client-an application that provides output to end users. The client uses a service, a business service that adheres to the following service interface:

Package COM.SPRING.JDBC;
Import java.util.List;
Public interface Service {
Public List gettasksnames ();
public void Settasksdao (Tasksdao Taskdao);
}
The client needs to access a business service object. It will use spring Beancontainer to "catch" a service object like this. The client can only program on the interface and rely on the container to provide a practical implementation. Also, this Serviceimpl class must implement all the methods that exist in the business service interface. The code looks as follows:

Package COM.SPRING.JDBC;
Import java.util.List;
public class Serviceimpl implements service{
Tasksdao Taskdao;
public void Settasksdao (Tasksdao Taskdao)
{
This.taskdao=taskdao;
}
Public List Gettasksnames ()
{
List tasks = Taskdao.gettasksnames ();
return tasks;
}
}
You should have noticed that the service needs a Tasksjdbcdao. This object, in turn, implements the Tasksdao interface. Therefore, we will inject DAO into the service through Beanfactory. Here, we happen to have a Tasksjdbcdao class-bean factory that can be used to achieve this goal. However, since this class derives from Jdbcdaosupport, we know that we need to inject a datasource or let the Bean factory inject the datasource for us. The bean configuration file now looks like this:

<?xml version= "1.0" encoding= "UTF-8"?
! DOCTYPE beans Public "-//spring//dtd bean//en"
"Http://www.springframework.org/dtd/spring-beans.dtd" >
<beans>
<bean id= "Datasourcedbdirect"
Class= "Org.springframework.jdbc.datasource.DriverManagerDataSource"
Destroy-method= "Close" >
<property name= "Driverclassname" value= "Oracle.jdbc.driver.OracleDriver"
<property name= "url" value= "Jdbc:oracle:thin: @localhost: 1521:ORCL"/>
<property name= "username" value= "Scott"
<property name= "password" value= "Tiger"
</bean>
<bean id= "Tasksdao" class= "Com.spring.jdbc.TasksJdbcDAO"
<property name= "DataSource"
<ref local= "Datasourcedbdirect"/>
</property>
</bean>
<bean id= "service" class= "Com.spring.jdbc.ServiceImpl"
<property name= "Tasksdao"
<ref local= "Tasksdao"/>
</property>
</bean>
</beans>
We see that the service bean makes the Tasksdao bean injected-it in turn causes the Datasourcedbdirect object to be injected. When we request a service bean, we get it through a DAO with DataSource. At this point, everything is ready. So what happens when the client accesses the bean container to get the service object? The bean container is instantiated and injected with a DataSource and a tasksdao-before the service is returned to the client. Now, our clients have become quite simple. It needs to communicate with Beanfactory, "grab" a service object and process it:

Package COM.SPRING.JDBC;
Import Java.util.Iterator;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client extends RuntimeException {
public static void Main (string[] args) throws Exception {
ApplicationContext CTX = new Classpathxmlapplicationcontext ("Springconfig.xml");
Service service = (service) Ctx.getbean ("service");
Iterator Tskiter = Service.gettasksnames (). iterator ();
while (Tskiter.hasnext ()) {
System.out.println (Tskiter.next (). toString ());
}
}
}
You must note that this client derives from the RuntimeException exception class. Spring throws a runtimeexceptions instead of checking the exception-runtimeexceptions should not be caught. Because capturing all the exceptions in your code is a complex task, the spring developer decides to throw runtimeexceptions to implement if you don't catch an exception, your application will break and the user will get the application exception. The second reason to use them is that most of the exceptions are unrecoverable, so your application logic cannot handle them again in any way.

  Five. Other advantages

In addition to the benefits of the spring framework described above, using the spring framework with your JDBC application has other advantages. These advantages include:

· The Spring Framework provides

Org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor interface and some implementations of this interface (for example, Simplenativejdbcextractor). This content is useful for accessing Oracle features via an Oracle connection or resultset.

· For creating Oracle.sql.BLOB (binary Large Objects) and Oracle.sql.CLOB (character large object) instances, Spring provides a class Org.springframework.jdbc.support.lob.OracleLobHandler.

· The Oraclesequencemaxvalueincrementer class provided by spring provides the next value for an Oracle sequence. It effectively provides the same information as you can directly use the following commands: "Select Somesequence.nextval from Dual" (where Somesequence is the name of your sequence in the Oracle database). The advantage of this approach is that the Datafieldmaxvalueincrementer interface can be used in a DAO hierarchy without being tightly coupled to Oracle-specific implementations.

  Six. Conclusion

This article focuses on using spring to write JDBC code that is more maintainable and less prone to errors. Spring JDBC offers some advantages, such as cleaner code, better exception and resource handling, and the ability to focus on business issues rather than complex task code. Also, it is worth noting that using the spring framework to be able to use very few code can achieve essentially the same functionality as traditional JDBC.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.