Spring JDBC

Spring JDBC简介

Spring所提供的JDBC抽象框架由四个不同的包组成:

核心包包含JdbcTemplate。这个类是一个基础类之一-Spring框架的JDBC支持提供并使用。

数据源包是实现单元测试数据库存取代码的重要的一部分。它的DriverManagerDataSource能够以一种类似于你已经习惯于JDBC中的用法:只要创建一个新的DriverManagerDataSource并且调用setter方法来设置DriverClassNameUrlUsernamePassword

对象包中包含类,用于描述RDBMS查询、更改和存储过程为线程安全的、可重用的对象。

支持包-你可以从这里找到SQLException翻译功能和一些工具类。

1) 模板设计模式

Spring JDBC
实现模板设计模式,这意味着,代码中的重复的复杂的任务部分是在模板类中实现的。这种方式简化了JDBC的使用,因为由它来处理资源的创建和释放。这有助于避免普通错误,例如忘记关闭连接等。它执行核心JDBC工作流任务,如语句创建和执行,而让应用程序代码来提供SQL并且提取结果。

2) Spring JDBC异常处理

Spring
框架特别强调在传统型JDBC编程中所面临的与下列方案有关的问题:

◆Spring提供一个抽象异常层,把冗长并且易出错误的异常处理从应用程序代码移到由框架来实现。框架负责所有的异常处理;应用程序代码则能够专注于使用适当的SQL提取结果。

◆Spring
提供了一个重要的异常类层次,以便于你的应用程序代码中可以使用恰当的SQLException子类。

借助于一个抽象异常层,我们成功地实现了数据库独立性而不必改变异常处理。例如,如果你把你的数据库从PostgreSQL改变为Oracle,那么你不必把异常处理从OracleDataException改变到PostgresDataExceptionSpring能够捕获应用程序服务器特定的异常并抛出一个Spring数据异常。

当处理异常时,Spring检查来自一个数据库连接的元数据可用性以决定数据库产品。它使用这种知识来把SQLException映射到其自己异常层次中的具体的异常上。因此,我们不需要担心专门性的SQL状态或错误代码问题;Spring的数据存取异常不是JDBC特定的,因此你的DAO不必绑定到JDBC(由于其可能抛出的异常)。

. Spring JDBC示例

在下面两个列表中,我们将使用前面用传统型JDBC实现的业务逻辑为例并且展示使用Spring JDBC版本是多么容易。首先,我们从一个简单的接口开始。

package com.spring.jdbc;

import java.util.List;

public interface TasksDAO {

 public List getTasksNames();

}

接下来,我们提供针对于TasksDAO接口的一种实现。

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());

}

 }

}

在上面的例子中,普通的和复杂的任务代码已经被移交到框架中。还应注意,借助于Spring JDBC,我们如何利用控制反转(IoC)容器来提供一种DataSource-我们仅把它注入到TasksJdbcDAO对象中。

控制反转背后的概念通常被表达为不要找我,让我找你好了IoC把一些任务移交到了框架中,并且脱离出了应用程序代码。不是让你的代码调用一个传统的类库,而是一个IoC框架调用你的代码。存在于许多API中的生命周期回调,例如相应于会话EJBsetSessionContext()方法,正是展示了这种方法。

DataSource必须被注入到这个类中(或者其超类中),这是通过setDataSource()方法实现的。所有配置细节都远离了业务逻辑或客户端代码;这增加你的应用程序的松耦合性并因此而提高了程序的可测试性和可维护性。作为选择,我们还能在JNDIservlet容器中建立一个DataSource,并用编程方式来检索它,然后把它注入到DAO对象中。下面是一个你可以使用的示例Spring bean配置文件-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

这个文件指示Spring bean容器实例化一个dataSourceDBDirect bean-它基于org.springframework.jdbc.datasource.DriverManagerDataSource类创建。

1) 基于Spring JDBC实现一个业务层

我们已经看到了一个简单的使用Spring JDBC的例子,在这种情况下,它从Spring BeanFactory(控制反转容器)中得到极少的帮助。现在,我们将超越这个简单的例子。让我们来探讨一下如何基于Spring JDBC实现业务服务。首先,让我们创建一个客户端-一个为终端用户提供输出的应用程序。该客户端使用了一个服务,一个遵守下面的Service接口的业务服务:

package com.spring.jdbc;

import java.util.List;

public interface Service {

 public List getTasksNames();

 public void setTasksDao(TasksDAO taskDAO);

}

客户端需要存取一个业务服务对象。它将使用Spring BeanContainer抓住这样的一个服务对象。客户端仅能针对接口编程并且依赖容器来提供一种实际的实现。而且,这个ServiceImpl类必须实现所有的存在于业务服务接口中的方法。该代码看上去如下所示:

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;

 }

}

你应该已经注意到,该服务需要一个TasksJdbcDAO。反过来,这个对象实现了TasksDAO接口。因此,我们将通过BeanFactory来把DAO注入到该服务中。在此,我们碰巧有一个TasksJdbcDAO-bean工厂可以使用它来实现这一目的。然而,既然这个类派生于JdbcDaoSupport,那么我们知道我们需要注入一个DataSource或让bean工厂为我们注入该DataSource。现在这个bean配置文件看上去如下所示:

?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

我们看到服务bean使得tasksDao bean被注入-它反过来又使dataSourceDBDirect对象被注入。当我们请求服务bean时,我们通过一个具有DataSourceDAO得到它。至此,一切就绪。因此,当客户端存取bean容器以得到服务对象时,会发生什么呢?该bean容器实例化并且注入一个DataSource和一个TasksDAO-在把服务返回到客户端之前。现在,我们的客户端变得相当简单了。它需要与BeanFactory进行通讯,抓住一个服务对象并处理它:

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());

}

 }

}

你必须注意,在此Client派生于RuntimeException异常类。Spring抛出了RuntimeExceptions而不是检查的异常-RuntimeExceptions不应该被捕获。由于在你的代码中捕获所有异常是一种复杂的任务,所以Spring开发者决定抛出RuntimeExceptions以便实现如果你不捕获一个异常的话,那么你的应用程序将会中断而且用户会得到该应用程序异常。使用它们的第二个理由是,绝大多数异常都是不可恢复的,因此你的应用程序逻辑不能以任何方式来再次处理它们。

另外的优点

除了上面描述的Spring框架带给JDBC中的优点外,与你的JDBC应用程序一起使用Spring框架还存在另外一些优点。这些优点包括:

◆Spring框架提供了org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor接口和这个接口的一些实现(例如SimpleNativeJdbcExtractor)。对于经由一个Oracle连接或ResultSet访问Oracle特征的情况来说,这些内容是非常有用的。

对于创建oracle.sql.BLOB(二进制大型对象)oracle.sql.CLOB(字符大型对象)实例来说,Spring提供了类org.springframework.jdbc.support.lob.OracleLobHandler

◆Spring
提供的OracleSequenceMaxValueIncrementer类提供了一个Oracle序列的下一个值。它有效地提供了与你直接使用下列命令:"select someSequence.nextval from dual"(其中,someSequence是在Oracle数据库中的你的序列的名字)所提供的一样的信息。这种方法的优点是,DataFieldMaxValueIncrementer接口可以用于一个DAO层次中而不必紧密地耦合于Oracle特定的实现。

 

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值