`
zhangde
  • 浏览: 19820 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

JDBCTemplate 数据读取机制

阅读更多

文章来源: http://publishblog.blogdriver.com/blog/tb.b?diaryID=1182919

 

JDBCTemplate 数据读取机制

JDBCTemplate 数据读取

一般的读取数据的步骤可以用下图表示:

查看更多精彩图片

 

l 确定需要读取的数据:这一步应该是我们程序员关心的重点。他是我们程序的原始需求。

l 通知数据库我们的需求:

在直接使用 JDBC 程序这一步主要是分成如下几步来完成的。

先注册一个驱动(驱动由不同的厂商或组织实现。对不同的数据库服务器有不同的实现)

典型的注册方法:

Class.forName("my.sql.Driver");

然后通过 DriverManager 来创建一个数据库连接。

接着我们的程序就通过这个数据库连接和数据库服务器交互。我们发送查询请求只是各种交互的一种。而我们的请求的内容是根据我们的需求而确定的(其实就是 Sql 语句需要查询的内容了)。

这部分的工作可分为三部分:

  和数据库服务器建立连接。

  根据需求组织请求内容(确定查询语句)。

  通过连接向数据库服务器发送请求。

在以上的三步中其中第一步和第三步是约定好的。在 JDBC 程序中的典型实现方式为

//第一步

Class.forName("my.sql.Driver");

conn = DriverManager.getConnection(dbUrl);

// 第二步

sql = GenerateSql();

// 第三步

stmt = this.conn.createStatement();

rs = stmt.executeQuery(sql);

在这里我们应该把更多的注意点关注到第二步。

l 等待的过程我们就无能为力。这个牵涉到的东西很多包括网络,驱动的实现以及数据库服务器的性能。

l 组织数据。这应该是我们实现取数据目的的前骤。把关系型数据组织成我们方便使用的类型。如实体对象等。(其实这部分的工作可以用其他的 O/R mapping 框架来实现,但是这个不是今天想讨论的问题)这一部分复杂多样。只能由我们自己来实现。

l 通知数据库服务器请求结束。这一部分的工作应包括清理一些数据库资源,如数据库连接等。虽然很繁琐但是很重要,如果不做的话很有可能造成资源泄漏,在严重的情况下可能引发 OutofMenory 错误,导致系统瘫痪。很多时候我们会忘掉这个步骤。这个部分最好由工具完成。

l 使用是我们目标的一个实现。不多提了。

从上面的分析可以看出有两部分有很大的灵活性。

1. 向数据库服务器发送请求的请求组织部分。说白了也就 sql 语句的写法。

2. 组织数据部分。数据库读出来后把数据组织成我们所需要的格式。

做为一个 Template JDBCTemplate 为我们做好了通用的动作,及除了上述两点外的说有动作。并为上述两点提供了灵活方便的接口。

核心的接口有两个 : PreparedStatementCreator RowCallBackHandler

l PreparedStatementCreator

该接口只有一个方法需要实现。 PreparedStatement createPreparedStatement(Connection con) throws SQLException; 定制我们自己的查询条件。

下面的英文节选自 Expert One ? on ? One J2EE Design and Development 中的描述。

关于这本书和 Spring 框架的关系可以这么理解书是框架的最好说明。或者说框架是书的附带源码。

The PreparedStatementCreator interface must be implemented by application-specific classes to create a java.sql.PreparedStatement , given a java.sql.Connection . This means specifying the SQL and setting bind parameters for an application-specific query or update, which will be run by the JdbcTemplate class. Note that an implementation of this interface doesn't need to worry about obtaining a connection or catching any SQLExceptions that may result from its work. The PreparedStatement it creates will be executed by the JdbcTemplate class. The interface is as follows:

   public interface PreparedStatementCreator {  

     PreparedStatement createPreparedStatement (Connection conn)

       throws SQLException;

   }

The following shows a typical implementation, which uses standard JDBC methods to construct a PreparedStatement with the desired SQL and set bind variable values. Like many implementations of such simple interfaces, this is an anonymous inner class:

   PreparedStatementCreator psc = new PreparedStatementCreator( ) {

 

     public PreparedStatement createPreparedStatement (Connection conn)

         throws SQLException {

       PreparedStatement ps = conn. prepareStatement (

         "SELECT seat_id AS id FROM available_seats WHERE " +

         "performance_id = ? AND price_band_id = ? ");

       ps.setInt( 1, performanceId);

       ps.setInt( 2, seatType);

       return ps;

     }

   };

The PreparedStatementCreatorFactory class is a generic helper that can be used repeatedly to create PreparedStatementCreator objects with different parameter values, based on the same SQL statement and bind variable declarations. This class is largely used by the higher-level, object-abstraction framework described below; application code will normally define PreparedStatementCreator classes as shown above.

 

 

 

 

l          RowCallbackHandler

The RowCallbackHandler interface must be implemented by application-specific classes to extract column values from each row of the ResultSet returned by a query. The JdbcTemplate class handles iteration over the ResultSet . The implementation of this interface may also leave SQLExceptions uncaught: the JdbcTemplate will handle them. The interface is as follows:

   public interface RowCallbackHandler {

     void processRow(ResultSet rs) throws SQLException;

   }

Implementations should know the number of columns and data types to expect in the ResultSet . The following shows a typical implementation, which extracts an int value from each row and adds it to a list defined in the enclosing method:

 

   RowCallbackHandler rch = new RowCallbackHandler() {

     public void processRow(ResultSet rs) throws SQLException {

       int seatId = rs.getInt(1) ;

       list.add(new Integer (seatId) );

     }

   };

The RowCountCallbackHandler class is a convenient framework implementation of this interface that stores metadata about column names and types and counts the rows in the ResultSet . Although it's a concrete class, its main use is as a superclass of application-specific classes.

The ResultReader interface extends RowCallbackHandler to save the retrieved results in a java.util.List :

   public interface ResultReader extends RowCallbackHandler {

     List getResults() ;

   }

The conversion of each row of the ResultSet to an object is likely to vary widely between implementations, so there is no standard implementation of this interface.

到这儿 JDBCTemplate 其实已经建立起了个很完毕的数据库读取机制。下面我们将 JDBCTemplate 是如何实现数据库的读取。我们就来看看如何使用 JDBCTemplate 来实现数据库的查询。

RowCallBackHandler 的使用

public class BookDaoJdbc extends com.jet.springtest.dao.AbstractDaoJdbc   {

public List readAllBook() {

      

              String sql = "SELECT id,name,publisher,isbn FROM spring.book ";

              getJdbcTemplate().query(sql, new RowCallbackHandler (){

                     public void processRow(ResultSet rs) throws SQLException {

                            Book currentBook = new Book();

                            currentBook.setFBookName(rs.getString("name"));

                            currentBook.setFPublisher(rs.getString("publisher"));

                            currentBook.setFIsbn(rs.getString("isbn"));

                            currentBook.setFId(new Integer(rs.getInt("id")));

                            fBooks.add(currentBook);

                     }

              });

}

              return fBooks;

 

 

 

 

}

注意看一下 new RowCallbackHandler() 部分。这部分其实是我们实现了一个 RowCallbackHandler 接口的匿名类。我们必须实现一个 processRow(ResultSet rs) 的方法供 JDBCTemplate 回调。跟踪一下可以发现有如下的调用路径。

 

 

 

说明:这里有两个很有用的技巧。

1   使用接口实现回调的功能。

2   内部类的实用。

问题你一定想问一下我们如何得到数据库连接,打开并关闭呢?这所有的动作都是由 Template execute 中帮我们完成的。通过下面的代码得到证实。

 

我们可以清晰地看到 Template 帮我们做的一切,不用再担心 Connection 没有关闭而导致系统垮掉的可能。

PreparedStatementCreator 的使用

在上面的例子中我们已经看到 RowCallBackHandler 的作用是在数据组织这一块。 PreparedStatementCreator 的作用就是为了“向数据库服务器发送请求的请求组织部分”而服务的了。

 

这里只是简单的演示和解释了一下 JDBCTemplate 中的数据读取的机制。他还提供很多其它的查询和更新的接口。简单的说 JDBCTemplate 可以让你只关注你需要关注的地方。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics