`

从设计不足的JDBC,说到数据库连接池

阅读更多

 

JDBC是Java里边一个很重要的组成部分,现代的很多软件应用,都和数据库相关,因此,JDBC起着日益重要的作用。即便一个Java开发工程师不怎么直接使用JDBC,而是使用ORM等框架,但是这些框架也是给予JDBC包装而来的。因此,JDBC的不足,也给这些ORM还有数据库连接池组件带来了很大的不便。

 

 

我们知道,Java的Statement(和PreparedStatement),在execute查询和执行语句时,都需要检查SQLException,这个SQLException实际上表示的涵义太宽泛了,这也就是我在题目中提到的“缺乏设计”,实际上,一个Statement,执行的时候出错,有着多种可能,应该把这些错误分一下类来设计,这样表示的更清楚。

 

比如。在Statement去执行一个SQL时,很有可能是其所依赖的Connection被关闭了,这个时候,执行语句跑出的SQLException实际上是不合适的,应该是SQLConnectionException;

 

 

 

比如,要去一个不存在的表中select,执行时,跑出SQLException实际上是很对的;

 

但是我们看到,不管JDBC的版本怎么提升,从来也没有出现过SQLConnectionException这种东西,不管SQL执行时除了什么错,都是SQLExceptin。这非常像当初刚刚学Java时,写一个接口,通通声明为抛出Exception....

 

(后来看了,SQLException有一些子类,但是这些子类,都是所,执行某个SQL时的错误,按照道理,都应该是数据库连接正常,但是SQL有问题,例如查询不存在的表等操作,而SQLConnectionException不应该是SQLException的子类)

 

那么这个问题会影响到什么呢?如果每次使用都是直接创建连接,使用并且关闭还好,遇到异常就关闭就完事了,但是我们知道,目前很多开发使用的都是连接池,池化连接的close不是真正的关闭,而是将连接送回池中。

 

例如代码为:

 

Connection conn = null;
try{

    conn = pool.getConnection();
    conn.....
}catch(Exception ex){
   ...
}finally{

  if(conn!=null)conn.close();
}

 

 问题在于,如果出现异常了(一般是SQLException),应该怎么处理?按照逻辑,应该是如果是SQL查了一个不存在的表之类的,当然是连接回池,如果是连接坏了,当然是直接关闭。

 

但是现在我们能判断吗?因为只有SQLException,我们判断不出来。

 

根据SQLException的Message判断吗?不同数据库,Message是不同的。。。

 

还有可恨的,大多数数据库连接池,实际上是不向外提供“真正关闭一个连接”这个操作时,当然,这么做的考虑是为了屏蔽池化连接和直接创建的连接的区别,但是,这个接口封上之后,面对的这种问题应该怎么处理呢?

 

目前。大多数连接池也有一种办法解决,就是配置一个SQL,每次取出一个连接用的时候,都先执行一下,如果出错,表示连接坏了,连接池(连接池自身当然能够真正关闭连接)真正关闭这个连接,给一个新的连接供外部请求者使用。但这是个拙劣的方法,因为一个SQL意味着和数据库的一个TCP交互,性能的损耗是客观存在的,高并发、高效率的系统不应该用这种方法。

 

如果JDBC能够区分,那么将省去了很多麻烦,不管在连接池内部处理还是外部处理,至少都是符合逻辑的。在这里也建议使用一些开源数据库连接池组件的朋友们,如果你要选择一种连接池,一定注意这种连接池这种情况下的处理,是怎样设计实现的,这一是表明了开发者考虑问题是否周全,而是关乎系统效率和稳定性。

 

可能有的朋友会问,Java不会这么缺乏好的设计吗?我其实也不希望Java有这种缺陷,希望有一种好的机制来解决我的问题,但是很可惜没有看到。之前曾经花了很大的力气研究Java的源码,曾经认为Java有很多地方值得学习,所以去研读。结果发现,有很多代码非常好,同时也发现很多代码很糟糕;甚至不是实现代码的问题,而是设计时粗枝大叶。没有想清楚使用者使用中的问题。

 

一时、一天细心容易做到,但是在职业生涯中总保持细心、周全的考虑问题并不是件容易的事情,所以虽然觉得这里有问题,但是也不是嘲讽或者责难别人,而是希望Java早一天认识到这些基础库的问题,对这些东西进行一些梳理和改进,做好基础语言,别盲目的追逐热点,把高楼大厦建立在沙滩上。

 

 

 

 

 

 

 

 

1
3
分享到:
评论
7 楼 windshome 2013-09-06  
我觉得一般分表、或者像大型数据库分区也行,总之存储层的性能存储层去解决,应用层只需要知道需要把数据存进去,还要再某个时间取出来就行。


跨库的事务,没有办法保证完整性,除非做很完整且啰嗦的完整性处理。跨表还好办。建议改成跨表方案,在一个连接、一个事务中保证完整性。

如果实在没有办法改结构,那么如果对数据一致性要求还那么高,那么就需要对每一个错误,做回滚。完成后,核对一致性,不一致的话,退回执行前的状态。这个太复杂了。
6 楼 Tyrion 2013-09-06  
windshome 写道
看到老兄你的意见很高兴,感觉JDBC不是粗糙而死缺乏好的设计和用心的设计,在设计时没有考虑使用者的真实情况。更别提设计JDBC 时,没有考虑将来会池化连接。

可气的不是这个,而是JDBC规范一版一版更新,这个早该提上日程的事情没有人考虑也没有人提。

在这个事情上,我倒是觉得通过上层去包装很绕,效果也很难好到哪里去,比如你提到Spring根据SQLState、ErrorCode做封装,这都像是房屋的地基不好,建筑到上边了,想办法来弥补,当然是一种方法,但是也很辛苦。

老兄对开源的推崇和我不同,我对开源的东西持慎重和保守态度,当然,很多开源的东西有非常高的价值,但是也有很多弊病,让人用起来爱恨难分。

说到连接池的实现和代码,我之前用的数据库连接池是自己写的,在非常苛刻的环境里运行了十年,从来没有因为连接池出过什么问题。为了设计和实现这个东西,参考和研究了一些实现。但是对开源框架,例如Spring、Hibernate等,却是不熟,我更熟悉的是底层JDBC、Socket连接、线程,所以老兄和我讨论这个可能会让我膛目结舌。不过也不妨碍说来听听,也许能给出点自己的看法,所谓愚者千虑或有一得嘛,说不定有高人看到给点启发性的意见呢。

呵呵,那就说下前段时间想了很久的涉及多数据源应用在框架层面保持事务一致性的问题。
场景是这样的:
1.我现在的项目中由于数据量等原因会涉及多数据库存储业务数据,典型的情况如千万级数据会分库分表来做。
2.有很多业务场景里一次请求中会涉及多个数据库的业务表记录的增删改,从业务逻辑上来说这些应该在同一事务中。
3.假设一次事务中要insert三个库中的业务表记录,我反编译了目前项目中的源码,实现方式是一个库对应会获取一个connection,业务方法开始是将这三个connection的自动提交事务属性置为false,完了在整个业务方法结束前将涉及到的三个connection逐个commit。

上述是我看到的源码,一开始我还以为是用XA来处理多数据源提交的业务场景,没想到我们项目里的框架代码是这么实现的,但对这种方式我有一点疑问,就是加入第一个connection已经commit成功,但第二个却失败了,这样将会产生错误数据。后来发现我们的框架在提交之前有个配置,可以校验一下connection的有效性,就是执行一下某个查询语句(如SELECT SYSDATE FROM DUAL),但这样也就是降低出错几率,总感觉实现方式还是粗糙。

不知你是否接触过这种场景,以及有没有什么更好的解决方案?
5 楼 windshome 2013-09-05  
看到老兄你的意见很高兴,感觉JDBC不是粗糙而死缺乏好的设计和用心的设计,在设计时没有考虑使用者的真实情况。更别提设计JDBC 时,没有考虑将来会池化连接。

可气的不是这个,而是JDBC规范一版一版更新,这个早该提上日程的事情没有人考虑也没有人提。

在这个事情上,我倒是觉得通过上层去包装很绕,效果也很难好到哪里去,比如你提到Spring根据SQLState、ErrorCode做封装,这都像是房屋的地基不好,建筑到上边了,想办法来弥补,当然是一种方法,但是也很辛苦。

老兄对开源的推崇和我不同,我对开源的东西持慎重和保守态度,当然,很多开源的东西有非常高的价值,但是也有很多弊病,让人用起来爱恨难分。

说到连接池的实现和代码,我之前用的数据库连接池是自己写的,在非常苛刻的环境里运行了十年,从来没有因为连接池出过什么问题。为了设计和实现这个东西,参考和研究了一些实现。但是对开源框架,例如Spring、Hibernate等,却是不熟,我更熟悉的是底层JDBC、Socket连接、线程,所以老兄和我讨论这个可能会让我膛目结舌。不过也不妨碍说来听听,也许能给出点自己的看法,所谓愚者千虑或有一得嘛,说不定有高人看到给点启发性的意见呢。
4 楼 Tyrion 2013-09-05  
JDBC对于SQLException的设计确实比较粗糙,所以当时看Spring对这块又重新根据各厂商的异常里的SQLState、ErrorCode做了一层封装,层次结构较清晰。能不能提升到API层面这个真心得靠运气,不过我对Java的规范层面的东西并不是很感冒,更多情况下是开源社区走在官方层面之前。

看来楼主研究过开源的连接池的代码,前段时间在看应用中涉及多数据源的事务在框架层面的解决方案时有些困惑,有空交流交流?
3 楼 windshome 2013-08-07  
但是没有连接错误的异常啊。别的是有分类。这个对后面连接池之类的设计是有很大影响的。
2 楼 sgq0085 2013-08-07  
贴主错了,BatchUpdateException, RowSetWarning, SerialException, SQLClientInfoException, SQLNonTransientException, SQLRecoverableException, SQLTransientException, SQLWarning, SyncFactoryException, SyncProviderException。这些都是继承至SQLException的。
就好比继承Exception的有很多种,但是为了方便直接cache Exception,这个跟设计无关吧,是程序员的事情
1 楼 maodou95838 2013-08-07  
拜读了。。。

相关推荐

    Java-jdbc数据库连接池总结.doc

    JDBC是一种“开放”的方案,它为数据库应用开发人员﹑数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API,分别是面向开发人员的API和...

    基于JAVA JSP数据库连接池的研究与实现的毕业设计,使用数据库连接池方式能对数据库的连接进行管理和维护,上层应用程序通过数据

    在这种策略思想的指导下实际开发出一个数据库连接池模块,使得上层应用通过本连接池访问数据库资源变得相对高效和容易,从实际上论证了这种设计方案的可行性。 关键词:连接池;数据库;JDBC;并发访问在基于JDBC的...

    Java_jdbc数据库连接池总结

    为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再...

    JDBC数据库编程实验

    一、实验目的: ...(5)理解数据库连接池的基本原理和思想,学会在tomcat服务器中配置数据库连接池,并掌握从连接池中获取连接的基本方法。 (6)初步理解数据访问层的基本设计方法,理解web的分层架构。

    基于JSP+JDBC的数据库连接池设计与实现(源码+文档).zip

    资源名字:基于JSP+JDBC的数据库连接池设计与实现(源码+文档)_jsp_BS架构_数据库连接池.zip 资源内容:项目全套源码+完整文档 源码说明: 全部项目源码都是经过测试校正后百分百成功运行。 适合场景:相关项目设计

    JDBC 3.0数据库开发与设计

    4.7.1 连接池数据源(Connection PoolDataSource) 4.7.2 连接池处理事件 4.7.3 三层环境下的连接池操作 4.7.4 连接池和DataSource实现 4.7.5 包含连接池的数据源配置 4.7.6 池连接对象对于语句的重新利用 ...

    jdbc连接池封装及ORM框架jdbc.rar

    数据库连接池封装和ORM框架封装 涉及到知识点:多种设计模式、注解、反射.通过该封装学习,可以加深对java基础的理解

    第2版_第4章_JDBC数据库访问技术.ppt

    数据库是Web应用程序重要组成部分,在Java Web应用程序中,数据库访问是通过Java数据库连接(Java DataBase ... 本章介绍使用JDBC驱动程序连接数据库和使用连接池技术连接数据库并设计应用程序的方法、步骤和实例。

    基于Servlet的学生管理系统,应用MVC的设计模式,使用c3p0数据库连接池,使用DBUTil框架简化JDBC操作.zip

    包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...

    基于BootStrap和SpringBoot的学生信息管理系统,支持增删改查等基础操作,适合个人web开发学习,毕业设计或课设等

    采用 c3p0 开源 JDBC 数据库连接池连接 MySql 数据库;发送 AJAX 请求获取 JSON 数据,并通过 Dom 动态加载页面;使用了 Spring - Test 与Junit 编写单元测试代码;使用了 Restful 设计风格,以 AJAX 发送 PUT 与 ...

    Java_JDBC由浅入深

    第十四节 编写一个简单的数据库连接池 74 14.1 为什么要使用数据库连接池 74 14.2 数据库连接池雏形 74 14.2 数据库连接池优化 77 14.2.1 对线程池加锁 77 14.2.2 连接不够用时抛出异常 77 14.3 数据库连接池之代理...

    基于JavaDruid+MySQL实现一个订餐管理系统源码+项目说明.7z

    该订餐管理系统是一个基于JavaDruid、MySQL、MySQL数据库连接池、JDBC等技术的食堂后台订餐管理系统,主要用来解决学校食堂拥挤、人员密集、等待时间长,无法进行线上订餐点菜服务等问题。 1、主要功能: ①线上点菜...

    ( 教师信息管理系统课程设计(数据库) 课程设计

    高校教师信息管理系统(数据库)课程...服务器用j2ee实现,主要是servlet和连接池,没有用到框架,可学习性不强,不过可以通过本案例了解android客户端和服务器的通信方法 3、数据库: MySQL,jdbc,没什么好说的了

    数据库实现课程设计报告

     了解数据库池的概念,掌握JDBC方式连接数据库,建立数据库池。  掌握数据库插入、查询、更新和删除的基本语句。  掌握数据库操作的基本步骤。  了解软件工程开发的流程,思考并掌握BBS系统的总体设计框架...

    使用JDBC连接,DBCP连接池实现的基础记账功能小程序。增删改查的练手实践项目。.zip

    数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫...

    day02_jdbc高级.md

    数据库连接池的概念,自定义数据库连接池,开源数据库连接池,自定义JDBC框架, DataSource 接口,归还数据库连接的方式,继承,装饰设计模式,适配器设计模式,动态代理

    课设&毕设&论文-JSP数据库连接池的研究与实现(源代码+论文).zip

    JavaWeb、jsp毕业设计源码,包括但不限于servlet、jsp、javabean、JDBC等。这些源码可以直接用于您的毕业设计,也可以作为您学习和参考的资料。 详细的毕业论文,内容详实、逻辑清晰、论述深入。论文主要包括项目的...

    jsp连接池成功之例

    数据库连接池配置 <br>环境:xp2+IE7.0+tomcat5.028+mysql5.018 <br>1.假定tomcat 安装目录为:D:\Tomcat5 <br>2.假定程序目录为: D:\web\WebRoot <br> 目录设置请看WebRoot.xml 中有下面这句代码:...

    数据库-数据库编码解决方案

    还是利用我在文章《使用JAVA动态代理实现数据库连接池》中使用的动态接口代理技术。首先我们设计Connection接口的代理类_Connection,这个代理类接管了Connection接口中所有可能获取到Statement或者...

Global site tag (gtag.js) - Google Analytics