Spring JDBC

JAVA就业套餐课:https://edu.csdn.net/combo/detail/1230

本章简介

在掌握了Spring容器的基础知识之后,我们要把它们应用到实际的程序之中。一个很好的起点是针对几乎所有企业程序都存在的需求:数据访问。几乎所有程序员都曾经处理过数据库访问,也都知道使用传统的JDBC进行数据访问具有一些缺陷。接下来我们将要学习Spring是如何改善数据访问过程中存在的缺陷的。

核心技能部分

 

Java持久化技术有很多种,Hibernate、iBATIS 和 JPA 只是其中的几种而已。尽管如此,很多程序还在以古老的方式把 Java 对象写入到数据库,就是JDBC技术。

使用JDBC这有什么不好吗DBC基于SQL,不要求我们掌握其他框架的查询语言,简单易学,因此学习成本低。另外,在使用 JDBC 时,可以更细致地调整数据访问的性能。JDBC 还允许我们利用数据库的特有功能,而其他框架可能不鼓励甚至禁止使用它们。

再者, JDBC可以让我们在比持久化框架低得多的层次上处理数据,能够访问和操作数据库里单独的字段。这种细致访问方法在有些程序里是很方便的,比如报表程序,如果把查询结果数据封装到对象里,而稍后惟一要做的只是把它分解为原始的数据进行输出,那封装过程就显的没有太大的意义了。

JDBC也不是十全十美的。它具有强大的功能、灵活性和其他一些优点,但也有缺点。

在讲解后面的内容之前,我们先来了解一下本章所有例子的数据模型。我们采用的是Oracle示范账户scott的emp表和dept表,针对这两张表,我们设计了两个实体类,用于封装查询结果,传递传递数据等,示例3.1是部门实体类:

 

 

第1章 

1.1 JDBC的缺陷

JDBC为我们提供了一个API 来处理数据库,我们要负责处理与数据库访问相关的一切事宜,其中包括管理数据库资源和处理异常。

对于曾经利用JDBC从数据库查询数据的程序员来说,示例3.3中根据主键查询唯一员工实体对象的代码应该并不陌生:

示例3.3 

 

失控的代码!这二十多行代码就是向数据库查询返回一个简单的对象。对于JDBC操作来说,简单易学是其特点,但为什么要用这么多行代码才能做到如此简单的事情呢际上不是这样的,只有几行是真正完查询操作的。无论是执行查询,更新,插入还是删除操作, JDBC都要求我们正确地管理连接和语句,还要处理可能抛出的SQLException,及时的释放资源。这显然造成了大量的代码重复。这似乎印证了 Pareto 法则:只有 20% 的代码是查询操作所必需的,而80%代码是样板代码。

但实际上这这些每次都需要重复编写的的样板代码是很重要的。清理资源和处理错误提高了数据访问的健壮性,没有这些操作,不能发现错误,就会让资源处于打开状态,从而导致意外的代码和资源泄漏。正是因为这些原因,我们让框架来处理这些样板代码,从而确保这些代码是存在的,而且是正确的。

Spring JDBC抽象框架所带来的价值将在以下几个方面得以体现,应用开发人员只需要完成粗体斜体字部分的编码工作,其它的由框架来自动完成:

l 定义数据库连接参数

l 打开数据库连接

声明SQL语句

l 预编译并执行SQL语句

l 遍历查询结果(如果需要的话)

处理每一次遍历操作

l 处理抛出的任何异常

l 处理事务

l 关闭数据库连接

1.1 配置数据源

无论使用什么形式的Spring DAO支持类,都需要配置对数据源的引用。Spring提供了多个选项用于在Spring程序里配置数据源,其中包括:

l 由JDBC驱动程序定义的数据源

l 基于连接池的JNDI数据源

l 基于连接池的本地数据源

数据库连接是一种关键的有限的昂贵的资源,频繁的建立和关闭数据库连接将造成很大的性能损失。这一点在多用户并发操作频繁的 web 应用程序中体现得尤为突出。

然而针对客户程序的连接请求,基于JDBC驱动程序定义的数据源每次都会创建一个新的连接。因此,此种数据源仅适合规模很小程序的程序或开发阶段。 对于已经准备进行发布的程序,建议使用从连接池获取连接的数据源。那么在了解如何创建基于连接池的JNDI数据源和本地数据源之前,先让我们了解一下数据连接池的基本原理和使用。

1.1.1 数据库连接池

对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。

数据库连接池负责创建、管理和释放数据库连接。当数据源被创建时,会预先创建出一定数量的连接。它允许应用程序重复使用连接池中现有的数据库连接,而不是每次重新建立一个数据库连接。事实上,当我们试图关闭一个从连接池获取的连接时,连接并没有被真的关闭,而是被连接池回收到池中,置于闲置状态,等待应用重新获取进行复用。这样就可以避免频繁创建和关闭连接,有效节省系统资源。

当并发访问量增大,现有数据库连接不够用时,连接池才会尝试从数据库获取一定数量新的连接,直到达到连接池能够分配的最大连接数量为止。

当并发访问量降低时,连接池又会释放空闲时间超过最大空闲时间限制的闲置连接来避免因为没有释放连接而引起的数据库连接遗漏和资源浪费。

数据库连接池产品的实现原理大致相同,下面我们就以 Apache 软件基金会旗下 Jakarta 小组开发的 Commons Database Connection Pooling(公共数据库连接池)为例,为大家讲解数据库连接池的使用。Spring和tomcat都内置了这个数据库连接池组件。

和其它连接池组件一样,DBCP 也通过实现 javax.sql.DataSource 接口来为应用提供数据源服务。示例3.4是 javax.sql.DataSource 接口的源代码,我们可以看到它有两个重载的 getConnection 方法,用于为应用程序提供数据库连接。

示例3.4

public interface DataSource  extends CommonDataSource,Wrapper {

 

Connection getConnection() throws SQLException;

 

Connection getConnection(String username,

String password) throws SQLException;

}

DBCP连接池组件的一个 DataSource 实现类叫做 BasicDataSource ,它定义了一些属性用于配置数据库连接池,我们来了解一些常用属性:

l initialSize :连接池启动时创建的初始化连接数量,默认值为0 。

l maxActive :连接池在任意同一时刻可以分配给应用程序使用的连接的最大数量。默认值为8。

l maxIdle:连接池中闲置连接的最大数量,超过此数量以外的空闲连接将被释放,如果设置为负数表示不限制,默认为8。

l minIdle:连接池中闲置连接的最小数量,当闲置连接数量低于这个数量时会创建新的连接,默认为0,表示不会创建连接

l maxWait  :最大等待时间,以毫秒为单位。当没有可用连接时,连接池等待应用释放连接的最大时间,超过该时间限制会抛出异常。默认-1,表示无限等待。应该设置合适的等待超时时间,如60000ms,避免因连接不够用,而导致请求被无限制挂起。 

l minEvictableIdleTimeMillis  :闲置连接被逐出连接池的时间期限,以毫秒为单位,默认为30分钟,可以适当做调整,需要和后端服务端的策略配置相关。

了解了DBCP数据库连接池组件的常用配置属性后,让我们来创建一个DBCP数据源对象,请看示例3.5:

示例3.5

 

 

需要注意的是,示例3.5只是创建了数据源对象,并配置了连接池参数,此时连接池并没有被初始化。当我们执行示例3.6中代码,即第一次调用数据源的getConnection方法时,数据源对象将会根据配置参数初始化数据库连接池,创建5个数据库连接,返回一个供应用使用,剩余4个处于闲置状态,保存在池中。请看示例3.6,通过数据源获得数据库连接。

示例3.6

Connection conn = ds.getConnection();

System.out.println(“NumActive:” + ds.getNumActive());//打印分配给应用的连接数量

System.out.println(“NumIdle: ” + ds.getNumIdle());//打印池中闲置连接数量

当应用程序退出时,我们应该执行数据源对象的close方法,关闭数据源,释放所有连接资源。

示例3.7

ds.close()

数据库连接池对象一般都是以唯一实例形式存在的,即单例。这样便于统一管理连接资源。当应用程序需要数据库连接时,都必须向这个唯一的数据库连接池对象发送连接请求。

接下来,让我们来学习如何在Spring中创建和使用数据源。在我们真正做项目的时候,如果可能,我们应该优先选择通过 JNDI 从应用服务器获取连接池数据源。记住这一点,下面我们来看一看如何配置 Spring 从 JNDI 获取数据源。

 

1.1.2 在Spring中使用JNDI数据源

Spring Web应用通常运行于一个JEE程序服务器里,比如WebSphere、JBoss或像 Tomcat这样的Web容器。这些服务程序可以配置数据源,然后通过JNDI(java 名字目录服务)暴露给应用程序,应用程序通过本地或远程加载数据源获得数据库连接。以这种方式配置数据源的好处是可以在应用程序之外对数据源进行独立管理。应用程序本身只需要在需要访问数据库时请求数据源即可。而且,程序服务器里管理的数据源通常具有更好的性能,并能够由应用服务器系统管理员进行热切换(修改数据源配置,无需重启服务器)。

下面,让我们来学习如何在Tomcat中配置JNDI数据源,如何在Spring中使用JNDI数据源。

1. 在tomcat中配置JNDI数据源

1) 添加数据库驱动程序

如oracle 数据库jdbc驱动程序ojdbc6.jar,将其添加到 tomcat根目录下面的lib目录下即可。

2) 添加数据库连接池组件

我们使用tomcat自带的Apache组织开发的开源数据库连接池组件——Commons Database Connection Pooling(公共数据库连接池)。该组件位于tomcat根目录下面的lib目录下,名为tomcat-dbcp.jar。

3) 配置数据源

打开tomcat根目录下面的conf目录下面的context.xml文件,如D:javaapache-tomcat-6.0.18confcontext.xml,在根元素内部的末尾添加如示例3.8代码:

示例3.8

 

 

4) 重启tomcat

观察启动日志信息,如果没有报错,则表示数据源配置成功。如果报错,根据报错信息定位是那个环节出了问题,解决问题。

2. 在Spring 应用容器中配置JNDI数据源bean

利用Spring,我们可以像使用Bean一样配置一个数据源(保存在JNDI里)的引用,并且把它作为依赖,注入到其他需要使用数据源的bean里。Spring 的 JndiObjectFactoryBean 类能够从 JNDI 获取任何对象(包括数据源),并且可以将它配置在applicationContext.xml中,作为Spring Bean 使用。示例3.9通过JndiObjectFactoryBean类配置了一个JNDI数据源:

示例3.9

属性 jndiName 用于指定 JNDI 资源目录和名称。目录为java:comp/env/,资源名称为jdbc/scott。另外需要注意的一点事,数据源作为数据库连接资源的统一管理者一般以单例形式存在。

为了示范如何应用数据源,接下来我们使用传统 JDBC 技术创建一个dao类,将其配置成bean,为其注入数据源,实现员工信息查询。 请看示例3.10:

示例3.10

 


  1. package dao.jdbc;
  2. @Component("empDaoJdbc")
  3. public class EmpDaoJdbc {
  4. @Resource(name="dataSource")
  5. private DataSource dataSource;
  6. public List search() {
  7. Connection conn = null;
  8. Statement st = null;
  9. ResultSet rs = null;
  10. List list = new ArrayList();
  11. try {
  12. 来源:teayear

    声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年9月20日
下一篇 2017年9月20日

相关推荐