`

如何在关闭数据库链接时,自动关闭由该链接创建的所有Statement

阅读更多
前提条件:
1 使用连接池
2 使用了spring的ioc,即DAO是单例的

提出这个问题是由于我们系统中的实际出现的状况
由于开发人员众多,素质参差不齐,开发时间紧迫,
出现了大量的不符合规范的代码以及错误代码.
常见的就是 在关闭链接的时候没有关闭链接的创建的所有的Statement
(关闭了部分,但不是所有)

所以想和 大家探讨一下该如何在代码层次实现关闭数据库链接时,自动关闭由该链接创建的所有的Statement.
我的思路是这样的

将"当前线程+当前链接"创建的所有Statement 放入一个ThreadLocal 对象内.
当关闭链接时, 从ThreadLocal 对象取出 所有的 Statement ,逐个关闭.

不知道这样的思路是否可行.
下面附上代码:

为了阅读方便没有写出全部的创建Statement的方法

public class ConnectionUtils {
	public static final ThreadLocal statementMap = new ThreadLocal();

	public static void initStatementMap(Connection conn){
		String key=String.valueOf(conn);
		Map map=(Map)statementMap.get();
		if (map==null){
			map=Collections.synchronizedMap(new HashMap());
			statementMap.set(map);
		}
		if (map.get(key)==null) {
			map.put(key, new ArrayList());
		}
	}
	
	public static 	void putStatement(Connection conn,Statement statement){
		Map map=(Map)statementMap.get();
		List list=(List)map.get(conn.toString());
		list.add(statement);
	}
	
	public static 	void closeAllStatement(Connection conn){
		Map map=(Map)statementMap.get();
		List list=(List)map.get(conn.toString());
		for (Iterator itor=list.iterator();itor.hasNext();){
			Statement stm=(Statement)itor.next();
			try {
				stm.close();
			} catch (SQLException e) {
			}
		}
	}
	
	public static Statement createStatement(Connection conn) throws SQLException{
		Statement statement=conn.createStatement();
		putStatement(conn,statement);
		return statement;
	}
	

	public static  CallableStatement prepareCall(Connection conn, String sql) throws SQLException {
		CallableStatement statement=conn.prepareCall(sql);
		putStatement(conn,statement);
		return statement;
	}


	public static   PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException{
		PreparedStatement statement= conn.prepareStatement(sql);
		putStatement(conn,statement);
		return statement;
	}


}


在dao内的getConnection时 可以这么写
	protected final Connection getConnection(){
		Connection conn=DataSourceUtils.getConnection(getDataSource());
		ConnectionUtils.initStatementMap(conn);
		return conn;
	}


关闭Connection时 可以这么写
	protected final void closeConnection(Connection conn) {
		ConnectionUtils.closeAllStatement(conn);
		DataSourceUtils.releaseConnection(conn, getDataSource());
	}


要创建Statement时可以这么写
pstmt = ConnectionUtils.prepareStatement(conn,bufSql.toString());


以上只是我的一些思路,虽然在本机测试是可以的,但是不知道到底实际上是否可行
还请看看 谢谢了

分享到:
评论
15 楼 poiuyt373 2007-07-12  

      楼上才是正解,原有代码不做任何修改;
      
      出现这种问题,spring完全没有用好。
14 楼 leadyu 2007-07-12  
建议不要这样,这样的话维护较为困难,我的方法是代理连接池,spring也可采用第三方数据源,写个connection代理,new YouCnnection(Connection delegate).这样对于系统是透明的,默默地把资源回收了

代理里面想解决关闭statement的事,不用说大家也知道怎么做了吧。

13 楼 huangpengxiao 2007-04-26  
在连接池情况下,也是被close()之后才可以分配给其他线程的

确定?
12 楼 fins 2007-04-22  
谢谢 你解开了我一大疑问啊

我对池的一些知识确实很匮乏 谢谢指点

"在连接池情况下,也是被close()之后才可以分配给其他线程的"
这句话正是我想知道的 谢谢
11 楼 LucasLee 2007-04-21  
fins 写道

所以我真正想问的是
" 使用 ThreadLocal对象记录 当前conn在当前线程内打开的所有的Statement.
这样的思路可以不 "??

我觉得这样没有什么问题。
但我不觉得应该用ThreadLocal来记录,一个Connection应该只给一个线程使用(在连接池情况下,也是被close()之后才可以分配给其他线程的。),所以用一般的容器类存放所有此连接上打开的Statement就可以了,在connection.close()时,调用容器中所有的Statement.close(),并清空容器。
10 楼 fins 2007-04-21  
Lucas Lee 写道
既然这样的话,我也觉得包装Connection,然后delegate到实际的Connection上,除了在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来;等Connection.close()时,调用所有Statement.close()。


可能是我没说明白

我知道这种方式可以 也知道是最好的实现方式

但我的核心问题就是
"在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来"
那么怎么记录? 你不能记录当前链接打开的所有的的Statement,因为这样是不安全的吧 因为使用了池,会出现关闭不想关闭的Statement的情况.
所以我真正想问的是
" 使用 ThreadLocal对象记录 当前conn在当前线程内打开的所有的Statement.
这样的思路可以不 "??

而不是该使用什么样的模式来实现这个功能

9 楼 likeblood 2007-04-20  
6楼正解
8 楼 LucasLee 2007-04-20  
既然这样的话,我也觉得包装Connection,然后delegate到实际的Connection上,除了在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来;等Connection.close()时,调用所有Statement.close()。
7 楼 spiritfrog 2007-04-20  
codeutil 写道

自己实现一下 java.sql.Connection等接口,把原来的connection包装一下就可以了阿.




以楼主项目的情况来看,有那么多的dao类要进行最小范围的重构,这样的办法应该是不错的。
另外楼主的方法应该也可行,只是增加了些代码量
6 楼 hpq852 2007-04-19  
装饰模式的经典场景.

另外好的连接池在回收Connection的时候会自动关闭ResultSet 和 Statement 的
5 楼 codeutil 2007-04-19  

自己实现一下 java.sql.Connection等接口,把原来的connection包装一下就可以了阿.


4 楼 fins 2007-04-19  
其实这些我知道
但是现在的前提是 系统已经开发完成
一共有2000多个dao 都使用了传统的方式

在进行最小的重构前提下,我在顶楼里提出的那种思路和方案是否可行呢
3 楼 realreal2000 2007-04-19  
使用jdbcTemplete是不错的办法,推广它的时间和培训时间应该不是难么难吧
2 楼 fins 2007-04-19  
楼上的有些高估我们的开发所采用的技术了

我们dao里就是要操作那些基本的 connection  statement resultset
在这个前提下有什么办法呢 我也很无奈

如果想从源头解决问题 那就是所有开发人员提高个人职业修养和素质
否则什么都没用
1 楼 LucasLee 2007-04-19  
这种方法不在源头解决,我看以后维护可能比较麻烦。
源头上统一使用一些jdbcTemplete方法避免直接管理connection和statement不就可以了?

相关推荐

    怎样实现关闭connection时自动关闭Statement和ResultSet (下篇)

    NULL 博文链接:https://rickgong.iteye.com/blog/2354177

    java数据库连接Statement

    java数据库连接Statement

    JAVAWEB链接数据库.pdf

    Java Web 连接数据库技术是指在 Java Web 应用程序中,使用 Java 语言连接和操作数据库的技术,该技术广泛应用于各种基于 Web 的应用程序。 知识点: 1. Java Web 连接数据库的概念和应用 2. 使用 Java 语言连接 ...

    java数据库连接PrepareStatement

    java数据库连接PrepareStatement

    神通数据库-数据库快速入门.pdf

    在模式中创建数据库对象或访问模式中的对象时,可在对象名前指定模式名。 • 支持数据备份和恢复 神通数据库的备份/恢复工具具有图形化的操作界面。用户利用备份工具可以对整个数据库、指定数据 库、或者指定库中的...

    JSP应用开发-web项目创建和数据库连接类的设计.pptx

    例如,在使用 MySQL 数据库时,需要将 mysql.jar 文件直接拷贝到 WebRoot\WEB-INF\lib 目录下。然后,需要加载 JDBC 驱动程序,在连接数据库之前,首先要加载欲连接数据库的驱动程序到 JVM。 建立数据库连接 在...

    java-利用GUI实现窗口学生管理系统(jdbc连接数据库-MySQL)

    2、编写程序实现显示功能选项,创建GUI界面,显示所有学生信息,实现学生添加界面 3、编写程序,实现数据查询功能,加载数据功能,读取数组内容,生成对象,GUI界面显示 4、编写程序实现添加学生功能,创建界面,提示...

    jdbc连接数据库的方式2

    如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。  6、在成批处理重复的插入或更新操作中使用...

    如何在Servlet中连接数据库

    在创建了数据库连接后,我们可以使用 `Statement` 对象来执行 SQL 语句。例如,我们可以使用 `executeQuery()` 方法来执行查询语句。 4. 处理查询结果 在执行了 SQL 语句后,我们可以使用 `ResultSet` 对象来处理...

    prepareStatement和Statement的区别

    首先,从创建时的区别开始,Statement 需要通过 Connection 对象的 createStatement() 方法创建,而 PreparedStatement 需要通过 Connection 对象的 prepareStatement() 方法创建,并且需要带有 SQL 语句。...

    jsp数据库脱裤脚本,脱各种数据库

    15. 本例中使用String对象来存储备份文件的路径和名称,使用File对象可以创建备份文件。 16. 使用BufferedWriter对象可以写入备份文件,使用flush()方法可以刷新缓冲区。 17. 使用close()方法可以关闭备份文件,...

    JDBC连接所有数据库步骤

    JDBC连接所有数据库步骤 1 将数据库的JDBC驱动加载到classpath中,在基于JAVAEE的WEB应用实际开发过程中,通常要把目标数据库产品的JDBC驱动复制到WEB-INF/lib下. 2 加载JDBC驱动,并将其注册到DriverManager中。 3...

    jsp连接数据库代码大全.pdf

    在连接 Oracle 数据库时,需要使用 Oracle 的 JDBC 驱动程序。JDBC 驱动程序是 Java 语言中访问数据库的标准 API。使用 Oracle 的 thin 模式连接数据库,需要将 JDBC 驱动程序放到服务器的类路径里。然后,在数据库...

    Java WEB访问数据库

    在使用statement获取jdbc访问时所具有的一个共通的问题是输入适当格式的日期和时间戳:2002-02-05 20:56 或者 02/05/02 8:56 pm。 通过使用java.sql.preparedstatement,这个问题可以自动解决。一个...

    基于JavaBean技术的数据库访问及应用

    JavaBean连接数据库实际上就是定义与数据库连接 类的属性主要有连接数据库的对象、记录集对象、St t对象等;其构造方法实现对数据库的连接,即给连接 ...关闭连接对象、Statement对象、记录集等对象的功能

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

    首先我们设计Connection接口的代理类_Connection,这个代理类接管了Connection接口中所有可能获取到Statement或者PreparedStatement接口实例的方法,例如:prepareStatement和createStatement。改变这两个方法使之...

    MySQL.rar_JDBC程序_statement_完整java开发中JDBC连接数据库代码

    加载JDBC驱动程序,提供JDBC连接的URL ,创建数据库的连接,创建一个Statement ,执行SQL语句 ,处理结果,关闭JDBC对象

    JAVA基础:将数据库操作封装到Javabean文档信息

    需要注意的是,在封装数据库操作时,不能简单地返回结果集(ResultSet 对象),因为结果集总是依赖于它使用的连接(Connection)对象。因此,当连接对象在方法内被关闭后,返回的 ResultSet 就没有用了。如果真的要...

    连接数据库实现图书管理系统.doc

    4. 创建 Statement 对象:使用 Connection 对象创建 Statement 对象。 5. 执行 SQL 语句:使用 Statement 对象执行 SQL 语句。 图书管理系统功能 本项目实现了图书管理系统的基本功能,包括: 1. 图书浏览:通过 ...

    数据库接口解释类包解释

    该方法将建立与数据库的连接。 在使用上面的方法之前,需要先在DriverManager类中注册JDBC数据库驱动程序,一般使用的方法为Class.forname(“Driver name”)。在注册之前,需要先把数据库驱动程序的路径添加到...

Global site tag (gtag.js) - Google Analytics