提高Java数据库访问效率的策略研究

时间:2022-05-19 12:10:57

提高Java数据库访问效率的策略研究

摘  ;要: 在开发基于Java的应用时,提高对数据库的访问效率是程序员重点要考虑的问题之一。研究、分析了Java通过JDBC访问数据库的四种访问类型,提出了在不同的使用过程中的选择方案。介绍了连接池等对数据库访问效率影响较大的预处理语句及数据库连接管理技术。探讨了当前使用最为普遍的Hibernate在配置连接池和使用缓存等方面的问题。

关键词: JDBC驱动程序; 连接池; 预处理; 缓存

中图分类号:TP39  ;  ;  ;  ;  ;文献标志码:A  ;  ; 文章编号:1006-8228(2014)12-05-03

Research on promoting efficiency of database on Java

Liu Bing, Pan Dabing, Yang Hui

(Dazhou vocational and technical college, Dazhou, Sichuan 635001, China)

Abstract: One of the most important questions for a programmer to meditate is how to improve the visiting efficiency of database when developing an application based on Java. After researching and analyzing fourvisiting types of Javato database by JDBC,different projects to choose in diverse situations are put forward. Pre-statement which will greatly affect the visiting efficiency, such as connection pool, and database connection management technology are introduced. The problems which are related to the use of Hibernate in connection pool and the cache usage are also briefly discussed in this article.

Key words: JDBC driver; connection pool; pre-statement; cache

0 引言

Java语言具有与系统平台无关、安全、稳定、易于使用和易于从网络上下载等特性,它不仅可以用来开发大型的应用程序,而且特别适合于Web应用的开发。Java技术的核心之一就是对数据库的访问,SUN公司为此提供了一种标准的SQL访问数据库的编程接口JDBC,用来支持对各种平台的数据库进行访问。

本文介绍了各种JDBC访问类型,在对它们进行分析、比较的基础上提出一个在使用过程中的选择建议;对通过JDBC建立数据库的连接提出了一个高效建立和管理的策略――连接池技术。另外,在对向数据库服务器发送SQL语句的过程中,对于如何使用Statement接口和PreparedStatement接口给出了一个选择建议;就当前常用的Hibernate技术在连接池和缓存等方面的使用作了相应介绍。

1 Java数据库访问机制

JDBC是一种用于执行SQL语句的Java API,是Java数据库连接技术的简称。一般JDBC有两层接口:驱动程序层和应用程序层。前者负责处理与具体驱动程序版本的所有通信,后者用于开发人员通过SQL调用数据库和取得结果。

在驱动程序层中有四种类型的驱动程序:①JDBC-ODBC桥驱动程序;②本地API驱动程序;③纯Java的网络协议驱动程序;④纯Java的本地协议驱动程序[7]。

在应用程序层中有四种重要的接口:①Java.sql.DriverManager,用于处理驱动程序的装载和建立新的数据库连接;②Java.sql.Connection,用于完成对某一指定数据库的连接;③Java.sql-Statement,用于管理在指定数据库连接上的SQL语句的执行;④Java.sql.ResultSet,用于从数据库返回结果集。

2 提高数据库访问效率的策略

2.1 选择合适的JDBC驱动程序

下面将对驱动程序层中的四种类型的驱动程序在访问数据库方面的优劣进行分析、比较,在此在基础上给出一个相应的选择建议。

⑴ JDBC-ODBC桥驱动程序:由于通常的DBMS都支持微软提出的ODBC规范,同时,它的配置也相当简单,因此这一机制可作为在具体应用开发中的一个选择。但这种方法有它的不足,即:其执行效率较低,对于大数据量存取的应用是不太适合的;它还要求客户端必须安装ODBC驱动,这显然也不适合于远程的数数据库访问。

⑵ 本地API驱动程序:它是其他三者利弊平衡的妥协产物。与类型一相比较,它借鉴了其利用客户端的本地代码库,加速了数据访问的执行,但却摒除了ODBC标准,而是支持厂商自己指定的性能扩展;与类型三相比较,它利用其多层的结构,即上层用Java实现,以利于跨平台应用和支持多数据库,下层改为本地代码,以利于加速执行的速度;与类型四相比较,借鉴了其与数据库结合紧密的优点,其相当一部分用Java实现,这对数据库性能有了很大的提升。这种类型的效率比起类型一来说虽然要高一些,但仍然需要在每台客户端上预先安装本地API库,因此不利于维护和使用。

⑶ 纯Java的网络协议驱动程序:在大型的企业级的应用中,后台的数据库往往不只一个,而且一般又是由不同的厂商支持。而该类型的驱动程序恰恰提供了对多种数据库的支持,与类型四相比,体现了它的灵活性优势。同时,该类型的驱动程序一般还提供了许多企业级的特征,例如SSL安全、支持分布式事务处理和集中管理等,这在实现某些特殊的用途方面将会带来一定的帮助。是否选用,要根据其应用本身是否需要对多DBMS的支持和某些扩展应用的需求。比较而言,这类驱动程序的体积最小、效率较高,具有最大的灵活性,其缺点是需要一个中间服务器的支持。另外,此类驱动程序采用标准的网络协议,可以被防火墙支持,是Internet应用理想的解决方案。

⑷ 纯Java的本地协议驱动程序:就当前一些主流DBMS的提供者来说,它们往往会为自己的数据库提供一个应用该类型驱动程序的JDBC接口。这种类型的驱动程序优势在于它和数据库本身结合比较紧密,而且是纯Java的实现,在企业级应用中,应该是首选。例如,对于Oracle数据库来说,Oracle、SilverStream、DataDirect等公司都提供了这种类型的驱动,就目前各种测试数据来看,该类型驱动程序的性能往往被评价为最高的和最可靠的,同时,其访问数据库的效率也有不错的表现。但由于其采用DBMS专用的网络协议,可能不被防火墙支持,在Internet应用中也会存在潜在安全隐患[8]。

通过上述分析、比较,我们用一个表来对这四种类型的驱动程序在不同情况下的选择顺序作一总结,如表1。

表1  ;JDBC驱动程序选择建议方案

2.2 使用连接池

在Java应用程序访问数据库的模式的步骤二中,需要通过JDBC来建立数据库连接,对连接的管理又往往是决定应用性能的一个重要因素。当前,对于连接的管理的最为有效的策略是使用连接池技术。

连接池的思想是:Web服务器可以事先预备好若干个连接对象,将这些连接对象存放在一个称为连接池的容器中,当某用户需要操作数据库时,只要从连接池中取出一个连接对象即可,当用户使用完该连接对象后,将该连接对象放回到连接池中。如果某用户需要操作数据库时,连接池中已没有连接对象可用,那么该用户就必须等待,直到连接池中有了连接对象[1]。

在应用程序中可以使用Java为我们提供的某些容器类(诸如:Vector、Stack等)来方便地构建连接池。在实际实现中,通常是将数据库连接作为一个对象存储在这些容器类对象中(即连接池)。

当连接池创建好后,若在连接池中设有空闲队列和已分配队列,则空闲队列存放未分配的连接,已分配队列存放正在使用的连接。当客户应用连接池请求数据库连接时,先查看池中有没有被分配的空闲连接,如果存在空闲连接则把空闲连接分配给客户,并作相应处理,主要的处理策略就是设置该连接为已使用即分配状态,即注册到已分配队列中。若连接池中没有空闲连接,则先看该连接池是否已达到最大连接数,若未达到则创建新连接并设置其为已分配状态即可,若已达到最大连接数则只能等待其他线程释放连接后才能获取,若超过允许的最大等待时间则此次请求无效。当客户释放连接时,应唤醒所有等待连接的客户线程并做相应的处理。如果连接释放后没有等待连接的客户线程,则把它重新放回连接池的空闲队列中,但并不关闭该连接[2]。

由于数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,可避免数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。

另外,数据库连接能够得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上也增强了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。在较为完备的数据库连接池实现中,还可根据预先的连接占用超时设定,强制收回被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄漏。

2.3 使用预处理

Java提供了高效率的数据库操作机制,这就是PreparedStatement对象,该对象被习惯性地称为预处理语句对象。

当向数据库发送一个SQL语句,比如Select*From employee,数据库库中的SQL解释器负责将SQL语句生成底层的内部命令,然后执行该命令,完成有关的数据操作。如果不断地向数据库提交SQL语句,势必增加数据库中SQL解释器的负担,影响执行速度。如果应用程序能针对连接的数据库,事先就将SQL语句解释为数据库底层的内部命令,然后直接由主数据库去执行这个命令,显然不仅能减轻数据库的负担,而且也能提高访问数据库的速度。

对于JDBC,如果使用Connection 和某个数据库建立了连接对象con,那么con就可以调用prepareStatement(String sql)方法对参数sql指定的SQL语句进行预编译处理,生成该数据库底层的内部命令,并将该命令封装在PrepareStatement对象中,那么该对象调用下列方法都可以使得该底层内部命令被数据库执行:

ResultSet executeQuery()

boolean execute()

int executeUpdate()

只要编译好了PrepareStatement对象,那么该对象可以随时执行上述方法,显然提高了访问数据库的速度。

2.4 使用Hibernate

Hibernate是基于Java的开源持久化中间件,它对JDBC实现了轻量级的封装。开发人员通过Hibernate提供的API可以很轻松地操作数据库。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Java Web应用中使用,完成数据持久化的重任。

但是在很多情况下Hibernate的性能比直接使用JDBC存取数据库要低,这是因为Hibernate的底层实现是通过JNDI(Java命名与目录接口)、JDBC、JTA(Java事务API)来实现的,Hibernate做的是持久化封装,无论封装有多高效,也没有直接操作JDBC效率高[6]。

然而,通过正确的方法和策略,在使用Hibernate的时候还是可以非常接近直接使用JDBC时的效率的,并且,在有些情况下还有可能高于使用JDBC时的执行效率。

在进行Hibernate性能优化时,需要考虑的方面较多,其中连接池的配置和缓存的使用是最为主要的方面。

⑴ 连接池的配置

在Hibernate中配置连接池的方式有以下三种。

方式1:使用Hibernate自带的连接池。

方式2:使用配置文件指定的数据库连接池。

方式3:从容器中获取得到连接池(如:Tomcat)。

Hibernate无论采用哪种方式获取连接池的连接,它对Java程序来说是独立的。Hibernate对其采用了配置化处理,也就是当想改变获取数据库连接的方式时,只要修改Hibernate的配置文件就可以了。

① 使用Hibernate自带的连接池

Hibernate自带的连接池性能不高,缺乏响应大批量请求以及容错能力,甚至还有BUG,在项目运用中不值得推荐。限地篇幅,本文对其配置方法不作介绍。

② 使用配置文件指定的连接池

笔者在这里推荐当今稳定而且主流的数据源,就是Hibernate支持的第三方连接池产品:C3P0,Proxool。

③ 从容器中获取得到连接池(如:Tomcat)

Hibernate想要从Tomcat中获取数据源,需要对Tomcat容器与Hibernate分别进行配置[6]。

⑵ 使用缓存

对于Hibernate这类ORM(Object Relation Mapping)而言,缓存就显得尤为重要,它是持久层性能提升的关键。虽然Hibernate通过对JDBC的封装来实现了内部状态的管理、OR(Object Relation)关系的映射等,但随之带来的就是数据访问效率的降低和系统性能的下降,而缓存正是弥补这一缺点的重要方法。

在Hibernate中主要有三种不同的缓存:一级缓存、二级缓存和查询缓存。一级缓存在Hibernate中对应的是session范围的缓存,也就是当session关闭时缓存即被清除,一级缓存在Hibernate中是不可配置的部分;二级缓存在Hibernate中对应的是SessionFactory范围的缓存,通常来讲SessionFactory的生命周期和应用的生命周期相同,二级缓存在Hibernate中是可以配置的,可以通过class-cache配置类粒度级别的缓存,同时也可通过collection-cache配置集合粒度级别的缓存;查询缓存在Hibernate同样是可配置的,默认是关闭的,可以通过设置cache.use_query_cache为true来打开查询缓存。

缓存的实现通常是通过key/value的Map方式来实现,在Hibernate的一级、二级和查询缓存也同样如此。一级、二级缓存使用的key均为po的主键ID,value即为po实例对象,查询缓存使用的则是查询的条件、查询的参数、查询的页数。value有两种情况,如果采用的是select po.property这样的方式,那么value为整个结果集,如采用的是from这样的方式,那么value为获取的结果集中各po对象的主键ID[6]。

3 结束语

就Java应用开发而言,恰当地选择JDBC驱动程序、使用连接池、对SQL语句进行预处理和使用Hibernate中的相关API等是提高数据库访问效率的一些主要解决方案。就软件技术而言,除本文提到的方法以外,在某些应用中,使用JavaBean技术、线程技术、优化查询语言和恰当地利用事务处理等也能够在一定程度上提升数据库的访问效率。此外,硬件设备的改善无疑是一个重要方面。因此,合理地选择及整合相关的技术方案,并结合实际开发环境,才可能够在更大的程度上提高数据库的访问效率。

受篇幅所限,本文没能详细地给出相关技术的具体设计与实现。作者旨在通过本文的研究使读者能从宏观层面把握相关技术,并能由此及彼展开对相关问题的探讨,以期获得最优的解决方案。

参考文献:

[1] 孙叶枫,宋中山.JSP中基于连接池的数据库访问技术[J].计算机应

用,2004.6:80-82

[2] 黄伟.在JSP中使用连接池优化数据库访问效率[J].计算机应用,

2002.4:67-70

[3] 耿祥义,张跃平.Java 2实用教程(第三版)[M].清华大学出版社,2006.

[4] 黄文,谢寄石.基于J2EE的数据库连接服务[J].电子科技大学学报,

2002.1:67-71

[5] (美)埃史尔.Java编程思想(第4版)[M].机械工业出版社,2007.

[6] 付京周.精通Hibernate 3.0[M].人民邮电出版社,2007.

[7] 张晓东.Java数据库高级教程[M].清华大学出版社,2004.

[8] (美)霍斯特曼.JAVA核心技术卷II[M].机械工业出版社,2008.

[9] 汪晓平,贾敬习,李功.精通Java网络编程(第二版)[M].清华大学出版

社,2009.

[10] 孙卫琴.Java网络编程精解[M].电子工业出版社,2007.

上一篇:技术侦查措施侦查实践研究 下一篇:基于项目式高校单片机课程改革与实践