Spring JDBC 的设计与实现

一、Spring JDBC的设计与实现

 

 

(一)应用场景

 

        在Java开发环境中,使用JDBC技术对关系数据库进行操作。通过JDBC,Java语言的客户端可以访问数据库的数据,比如CRUD等对数据库的基本操作。尽管在实际应用中,对应不同的数据库产品,还需要有相对应的数据库驱动作为支持,但由于有了JDBC和SQL,对数据库应用而言,其程序的可移植性在很大程度上得到了增强。

        JDBC已经能够满足大部分用户操作数据库的需求,但在使用JDBC时,应用必须自己来管理数据库资源,比如数据库连接、数据库事务、数据库异常等,对底层的数据库实现还有一定的依赖。作为应用开发平台的Spring,对数据库操作需求提供了很好的支持,并在原始的JDBC基础上,构建了一个抽象层,提供了许多使用JDBC的模板和驱动模块,为Spring应用操作关系型数据库提供了更大的便利。这些设计好的模块,封装了数据库数据存取的基本过程,并在具体的操作步骤上为用户提供了定制空间(模板模式的使用)。通过这种方式,一方面提高了应用开发的效率,另一方面又为应用程序开发提供了灵活性。另外,在Spring建立的JDBC的框架中,还设计看一种更面向对象的方法,相对于JDBC模板,这种实现更像是一个简单的ORM工具。为应用提供了另外一种选择。下面将对这两种设计进行详细分析。

 

 

(二)设计概要

 

        Spring JDBC提供了一系列的模板类为应该提供便利,在介绍Spring JDBC的设计之前,先回顾一下模板模式。

        如图,在模板模式中,一般会定义一个抽象方法,在抽象方法中定义了模板方法(TemplateMethod)。在模板方法中,会对处理进行描述,同时,这个描述中的一些方法(PrimitiveOperation)是可以灵活处理的。模板使用者只需要实际一个具体的类,继承模板类,然后制定那些具体的方法,这样既能重用整个模板的处理框架,又能发挥具体子类的灵活性,所以这种模式被称为模板模式。这种模式在Spring中是很常见的,比如JdbcTemplate、HibernateTemplate等。在这些Spring设计的模版中,大部分封装了对JDBC和Hibernate处理的通用过程,比如数据库资源管理、Hibernate的Session管理等,在应用使用时,只需要实际资金定制化的或者和应用相关的部分就可以了。

 

 

二、Spring JDBC中模板类的设计与实现

 

 

(一)设计原理

 

        在Spring JDBC中,JdbcTemplate是一个主要的模板类,它的继承关系如下:

 

 

         从类继承关系上看,JdbcTemplate继承了基类JdbcAccessor和接口JdbcOperation。在基类JdbcAccessor的设计中,对DataSource数据源进行管理和配置。在JdbcOperation接口中,定义了通过JDBC操作数据库的基本操作方法,而JdbcTemplate提供这些接口方法的实现,比如execute()方法、query()方法、update()方法等。

 

 

(二) JdbcTemplate的基本使用

 

        在Spring JDBC中,JdbcTemplate是操作数据库的类,它提供了许多便利的数据库操作方法,比如查询、更新等。而且,在Spring中,有许多类似于JdbcTemplate的模板类,使用方法也都非常类似,比如在ORM包中会看到的HibernateTemplate等。

       简单看来,这些在Spring中涉及和实现好的模板类都是通过回调函数的使用来完成其功能的。对满足应用的数据库操作需求而言,应用程序只需要在回调接口中实现自己需要的定制行为,比如使用客户设计好的SQL语句等,就能够完成对数据库中数据的操作。不过,Spring JDBC在这层回调函数的基础上进行了再次封装,为用户提供了许多操作数据库的现成方法,在一定程度上便于用户使用。JdbcTemplate是一个很重要的类,它的继承关系和主要的实现方法如下:

 

         可以看到一系列的execute()方法、query()方法、update()方法的实现,具体实现可参考源码。在使用JdbcTemplate的execute()方法通过StatementCallBack<T>回调的使用方法如下,通过该方法可以定制个性化 的ORM方法。

 

 

        在模板方法的回调方法doInStatement()中是用户对数据库进行操作的代码,可以由Spring来完成(excute(String sql))或者由用户直接完成(excute(StatementCallBack<T> callBack)),然后通过JdbcTemplate来完成相应的数据库操作。

 

 

(三)JdbcTemplate的execute()方法实现

 

        下面以JdbcTemplate.execute()为例进一步分析JdbcTemplate中的代码是如何完成使命的。这个方法是在JdbcTemplate中被其他方法调用的基本方法之一,应用程序往往使用这个方法来执行基本的SQL语句。在execute()的实现中看到了对数据库进行操作的基本过程,比如需要取得数据库Connection,根据应用对数据库操作的需要创建数据库的State-ment,对数据库操作进行回调,处理数据库异常,最后把数据库Connection关闭等。这里展示了使用JDBC完成数据库操作的完整过程,只是Spring对这些较为通用的JDBC使用通过JdbcTemplate进行了一个封装而已。Execute()方法的源码和设计如下:

JdbcTemplate.execute()

 

 

 

 

(四)JdbcTemplate的query()方法实现

 

        JdbcTemplate中给出的query()、update()等常用方法的实现,大对数都是依赖于前面提到的execute()方法。下面是quary()方法是设计时序和源码实现:

 

JdbcTemplate.query()

 

 

 

(五)使用数据库Connection

 

        在以上这些对数据库的操作中,使用了工具类DataSourceUtils。Spring通过这个辅助类对数据库的Connection进行管理,比如利用它来完成打开和关闭Connection等。Data-SourceUtils对这些数据库Connection管理的实现如下:

 

DataSourceUtils.getConnection()

 

DataSourceUtil.doGetConnection()

 

        DataSource可以使用DBCP连接池或C3P0连接池,然后在IoC容器中配置好后交给Jdbc-Template就可以使用了。同时,有了JdbcTemplate封装的方法,使一些简单的JDBC操作变得非常方便。JdbcTemplate提供了许多现成的查询方法,比如queryForInt()、queryForObj-ect()等,已经能够很好的满足一些简单的JDBC查询处理了。和查询一样,JdbcTemplate也提供了许多不同参数类型的update()方法供用户使用,这些update()方法实现原理与query()方法基本相同。

 

 

三、Spring JDBC中DBMS操作对象的实现

 

 

        前面介绍了JdbcTemplate提供了许多简单的查询和更新功能。但是,有时可能需要更高层次的抽象,以及更面向对象的方法来访问数据库。Spring为我们提供了org.springfra-mework.jdbc.object包,其中包含SqlQuery、SqlMappingQuery、SqlUpdate和StoredProced-ure等类,这些类都是Spring JDBC应用程序可以使用的。但要注意,在使用这些类时需要为它们配置好JdbcTemplate座位其基本的操作实现,因为在它们的功能实现中,对数据库操作的实现基本上还是依赖于JdbcTemplate来完成的。

        下面将对Spring JDBC中的一些DBMS操作对象的实现进行分析。DBMS对象基本继承关系如下:

        在这个继承关系图中可以看到RdbmsOperation的一系列子类,不然StoreProcedure、  SqlQuery、MappingSqlQuery、SqlUpdate等。这些子类构成了DBMS体系,为通过JDBC完成数据库操作提供了更强大的功能。

 

 

(一)SqlQuery的实现

 

        Spring除了提供对JDBC的基本操作的支持之外,还为应用在更高层面上使用关系型数据库提供了许多支持,这些支持都建立在Spring JDBC实现的基础是哪个。这样,用户可以省去许多重复的手工代码,充分发挥框架的作用。比如,可以使用MappingSqlQuery将数据库表的数据记录直接映射到一个对象集合,这是一个很有用的特性,类似于一个简单的ORM实现。

        在了解这个特性的实现之前,可以先回顾一下它的基本用法。

 

 

        可以看到,对MappingSqlQuery使用的整个过程是非常简洁的。在设计好数据的映射代码后,查询得到的记录会被封装好转换为对象List。一条查询记录对应于一个数据对象,即可以吧数据库的记录直接映射成为Java对象在程序中使用,又可以避免使用第三方的ORM工具的配置,这对于简单的数据映射场景十分方便。mapRow()方法的实现中提供的数据转换规则和Hibernate的hbm文件的作用是非常相似的。

        在这个之后,我们只需要创建好MappingSqlQuery实现类对象,设置好SQL语句,设置好SQL参数,然后调用ScategoryMappingQuery对象的execute()方法即可。下面我们看一下declareParameter()方法与execute()方法的实现:

 

RdbmsOperation.declareParameter()

 

        从代码可以看出,RbdmsOperation实现的参数声明和完成并不复杂,只是把需要声明的参数加入一个声明参数列表。为了防止参数的重负加入,需要对isCompiled变量进行。isComplied变量在compile()方法调用时设置,标识compile()过程已经执行过了。该过程执行完后将执行execute()方法。

 

SqlQuery.execute()

 

 

 

        1)首先执行RdbmsOperationvalidateParametes()方法对SQL语句参数进行验证,该方法中先执行了checkCompiled()方法,检查是否执行compile()过程,若未执行,则调用comp-ile()方法执行。

 

RdbmsOperation.validateParameters()

 

 

RdbmsOperation.checkCompiled()

 

RdbmsOperation.compile()

 

RdbmsOperation.compileInternal()

 

        2)最后调用JdbcTemplatequery()方法进行数据库操作,通过execute()方法绑定PrepardStatementCallback回调,最终通过PrepatedStatement进行数据库操作,得到结果后通过ResultSetExtractor结果集对象处理。ResulteSetExtractor进行结果集处理的过程在Prepar-dStatementCallbackdoInPreparedStatement()回调方法中进行。

 

JdbcTemplate.query()

 

 

 

RowMapperResultSetExtractor.extractData()

 

        下面是该execute()方法的具体实现,在该实现中需要传入的参数有两个,一个是PreparedStatementCreator对象,另一个是PreparedStatementCallback实现对象。该方法里首先创建数据库Connection,然后使用PreparedStatementCreator创建PreparedStatement对象,最后调用PreparedStatementCallback实现对象的doInPreparedStatement()方法执行使用PreparedStatement执行数据库操作得到结果集,并使用ResultSetExtractor的extract-Date()方法处理结果集。

 

JdbcTemplate.execute()

 

PreparedStatementCreatorFactory.createPreparedStatement()

 

        在这里,通过这些封装和Spring提供的模板代码,只需要定义SQL语句和SqlParameter就能够满足需求。同时,这些特性也大大增强了应用代码的模块化和可维护性。

        通过分析发现,最后的数据库操作还是由JdbcTemplate来完成的。在这里可以了解对JdbcTemplate的灵活应用。从另一方面来看,这些已有的Spring JDBC实现对JdbcTemplate的扩展,已经直接使用JdbcTemplate完成复杂数据库操作的应用而言,也是很好的参考。通过使用Spring JDBC提供的SqlQuery基本特性,可以免去手工处理ResuktSet数据,并对其中每一条记录进行逐个迭代,手工转化为Java数据对象的繁琐过程。

 

 

猜你喜欢

转载自blog.csdn.net/weweeeeeeee/article/details/81136194