<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Junky's IT Notebook

    統計

    留言簿(8)

    積分與排名

    WebSphere Studio

    閱讀排行榜

    評論排行榜

    Why Spring JDBC?

    Why Spring JDBC?

    Why Spring JDBC? Why Spring JDBC?

    by Vikram Veeravelu
    05/09/2006

    Spring is a lightweight application framework. In many cases, Spring can elegantly replace services traditionally provided by Java EE application servers. Spring is both comprehensive and modular. With its layered architecture, it gives the developer flexibility to use any part of it individually. Spring consists of a number of modules, such as the IoC container, AOP, MVC, persistence, DAO, and remoting. These modules are fairly loosely coupled: some can be used without using the others. There is nothing as such as a Spring application: you can opt to use some, most, or all of the components supported by Spring framework to build your application. And, since Spring is open source, it can be used in discovering concrete examples of good application design principles.

    The easiest way to get going with Spring, in many instances, is through Spring JDBC. The JDBC support provided by the Spring framework is not tightly coupled with other parts of Spring, which boosts the maintainability of code. This article shows how any application that uses JDBC directly (i.e., not through some O/R mapping framework that itself uses JDBC) can easily benefit from Spring.

    Traditional JDBC

    There are many positive aspects of traditional JDBC that have allowed it to play a significant role in many J2SE and J2EE applications. However, there are some characteristics that make it unfortunately difficult to use:

    • The developer needs to deal with lot of plumbing and infrastructure, such as endless try-catch-finally-try-catch blocks.
    • Applications need complex error handling to ensure that connections are properly closed after they're used, which makes the code verbose, bloated, and repetitive.
    • JDBC uses the rather uninformative SQLException.
    • JDBC has no exception hierarchy.

    SQLException is thrown in response to any error, whether it originates in the JDBC driver or in the database, which makes it difficult to understand what actually went wrong. For example, if the SQL object is invalid or has been locked, an SQLException is thrown. Debugging such exceptions involves examining the SQL state value and error code, which requires more time. Worse, the meaning of SQL state value and error code varies between databases.

    Writing JDBC code is arguably not a easy job because of this repetitive overhead. To illustrate this, here's an example of traditional JDBC used 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));
            }
        }
    }
    		

    A tremendous amount of routine code is necessary in the above example, in addition to the SQL code that actually queries the database. The getConnection() method has nothing to do with our tasks, and even the getTasksNames() method contains just two lines of code that are specific to the task at hand. The rest is generic plumbing code.

    The many positive aspects of JDBC have allowed it to play a significant role in many J2SE and J2EE applications. However, as you've seen, there are some characteristics that make it more difficult to use than we might desire. These tedious and sometimes frustrating characteristics of JDBC have led to the creation of publicly available JDBC abstraction frameworks (such as SQLExecutor and Apache Jakarta Commons DBUtils), as well as an innumerable amount of homegrown JDBC application frameworks. One publicly available JDBC abstraction framework is Spring framework's JDBC abstraction.

    Introduction to Spring JDBC

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

    • The core package contains the JdbcTemplate. This class is one of the fundamental classes provided by and used by the Spring framework's JDBC support.
    • The datasource package is a great fit for unit testing database access code. Its DriverManagerDataSource can be used in a way that is similar to what you are already used to from JDBC: just create a new DriverManagerDataSource and call the setter methods to set DriverClassName, Url, Username, and Password.
    • The object package contains classes that represent RDBMS queries, updates, and stored procedures as thread safe, reusable objects.
    • The support package is where you can find the SQLException translation functionality and utility classes.
    The Template Design Pattern

    Spring JDBC implements the Template design pattern, meaning the repetitive plumbing parts of the code are implemented in template classes. This approach simplifies the use of JDBC, since it handles the creation and release of resources. This helps to avoid common errors like forgetting to close the connection. It executes the core JDBC workflow tasks like statement creation and execution, leaving application code to provide SQL and extract results.

    Spring JDBC Exception Handling

    The Spring framework addresses the problems faced in traditional JDBC programming with the following solutions:

    • Spring provides an abstract exception layer, moving verbose and error-prone exception handling out of application code into the framework. The framework takes care of all exception handling; application code can concentrate on extracting results by using appropriate SQL.
    • Spring provides a significant exception hierarchy for your application code to work with in place of SQLException.

    With the help of an abstract exception layer, we achieve database independence without having to change the exception handling. For example, if you change your database from PostgreSQL to Oracle, you do not have to change the exception handling from OracleDataException to PostgresDataException. Spring catches the application-server-specific Exception and throws a Spring data exception.

    When dealing with exceptions, Spring examines the metadata available from a database connection to determine the database product. It uses this knowledge to map SQLException to the correct exception in its own hierarchy. So, we need not worry about proprietary SQL state or error codes; Spring's data access exceptions are not JDBC-specific, so your DAOs are not necessarily tied to JDBC because of the exceptions they may throw.

    Spring JDBC Example

    In the next two listings, we'll take the business logic we previously implemented in traditional JDBC and show how much simpler the Spring JDBC versions are. We begin 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 above example, generic and plumbing code has been moved to the framework. Also note how along with Spring JDBC, we make use of the Inversion of Control (IoC) container to provide a DataSource that we can inject into the TasksJdbcDAO object.

    The concept behind Inversion of Control is often expressed as "Don't call me, I'll call you." IoC moves the responsibility for making things happen into the framework, and away from application code. Instead of your code calling a traditional class library, an IoC framework calls your code. Lifecycle callbacks in many APIs, such as the setSessionContext() method for session EJBs, demonstrate this approach.

    The DataSource has to be injected into this class (or rather its superclass) via the setDataSource() method. All configuration details stay out of the business logic or client code; this increases the decoupling of your application and thereby the testability and maintainability. Alternatively, we can set up a DataSource in the JNDI or servlet container, retrieve it programmatically, and inject it into the DAO object. Here's a sample Spring bean configuration file, SpringConfig.xml, that you could use:

    				<?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 that is created based on the org.springframework.jdbc.datasource.DriverManagerDataSource class.

    Implementing a Business Layer over Spring JDBC

    We have already seen a simple example of using Spring JDBC and in that case, it had very little help from the Spring BeanFactory (the Inversion of Control container). Now we will go beyond the simple example. We are going to see how we implement the business services on top of Spring JDBC. First, let us create a Client, an application that produces output for end users. The Client makes use of a Service, a business service that conforms 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 the Spring BeanContainer to get hold of such a service object. The client can just program against the interface and rely on the container to provide an actual implementation. Also, the ServiceImpl class has to implement all of the methods present in business service interface. The code will look 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 already noticed that the Service requires a TasksJdbcDAO. This object, in turn, implements the TasksDAO interface. So we will inject DAO to the service through the BeanFactory. We happen to have the TasksJdbcDAO class that the bean factory can use for this purpose. However, since this class extends from JdbcDaoSupport, we know we need to inject a DataSource, or have the bean factory inject that 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 the Service bean gets the tasksDao bean injected, which in turn gets the dataSourceDBDirect object injected. When we ask for the Service bean, we get it with a DAO that is ready to go with a DataSource. Everything's ready to roll. So what happens when the Client accesses the bean container to get the Service object? The bean container instantiates and injects a DataSource and a TasksDAO before returning the Service to Client. Our Clientbecomes quite simple now. It needs to communicate with the BeanFactory, get hold of 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 have noticed Client extending RuntimeException. Spring throws RuntimeExceptions instead of checked Exceptions. RuntimeExceptions should not be caught. As it is a complex task to catch all of the exceptions in your code, the Spring developers decided to throw RuntimeExceptions so that if you do not catch an exception, your application will break and the user will get the application exception. Their second reasoning is that most exceptions are unrecoverable, so your application logic cannot deal with them anyway.

    Other Advantages

    Besides the advantages the Spring framework brings to JDBC, described in some detail above, there are several other advantages to using the Spring framework with your JDBC applications. These include the following:

    • The Spring framework provides the org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor interface and some implementations (such as SimpleNativeJdbcExtractor) of this interface. These are useful for accessing Oracle features via an Oracle connection or ResultSet when the connection is "wrapped" by another DataSource (such as that used with some application servers) or obtained through certain connection pools.
    • For creating instances of oracle.sql.BLOB (binary large object) and oracle.sql.CLOB(character large object), Spring provides the class org.springframework.jdbc.support.lob.OracleLobHandler.
    • The Spring-provided OracleSequenceMaxValueIncrementer class provides the next value of an Oracle sequence. It effectively provides the same information that would be provided if you used the following command directly: select someSequence.nextval from dual (where someSequence is the name of your sequence in the Oracle database). An advantage of this approach is that the DataFieldMaxValueIncrementer interface can be used in a DAO hierarchy without tight coupling of the Oracle-specific implementation.

    Conclusion

    This article has focused on the use of Spring to write JDBC code that is more maintainable and less error-prone. Spring JDBC provides benefits such as cleaner code, better exception and resource handling (at least than what I usually write using traditional JDBC), and the ability to really focus on the business problem instead of on plumbing code. It is noteworthy how much less code is required with the Spring framework to implement essentially the same functionality as with traditional JDBC.

    Further Reading

    Vikram Veeravelu is working with a Software company in Chennai.

    posted on 2006-05-17 00:32 junky 閱讀(2496) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲国产精品无码中文lv| 亚洲爱情岛论坛永久| jiz zz在亚洲| 成人免费男女视频网站慢动作| 亚洲欧洲综合在线| 国产精品免费网站| 亚洲不卡1卡2卡三卡2021麻豆| 国国内清清草原免费视频99| 亚洲国产精品久久人人爱| 久久久久久曰本AV免费免费| 亚洲成aⅴ人片在线影院八| 在线v片免费观看视频| 亚洲一区AV无码少妇电影| 色www永久免费视频| 亚洲AV成人精品日韩一区| 无码专区一va亚洲v专区在线| 全黄A免费一级毛片| 亚洲精品线路一在线观看| 国内精品久久久久影院免费| 亚洲av无码乱码国产精品| AV大片在线无码永久免费| 亚洲精品自偷自拍无码| 亚洲国产一成久久精品国产成人综合 | 久久国产高潮流白浆免费观看| 亚洲色图视频在线观看| 全免费a级毛片免费看不卡 | 天堂亚洲免费视频| 亚洲国产精彩中文乱码AV| 中文免费观看视频网站| 综合偷自拍亚洲乱中文字幕| 亚洲熟妇av一区二区三区漫画| 免费无码中文字幕A级毛片| 亚洲性线免费观看视频成熟| 波多野结衣中文一区二区免费 | 两个人看的www免费高清| 久久精品国产亚洲av日韩| 四虎永久在线精品免费网址| 免费国产va视频永久在线观看| 亚洲人成网站影音先锋播放| 青草草在线视频永久免费| 国产免费阿v精品视频网址|