2007-04-19
如何在关闭数据库链接时,自动关闭由该链接创建的所有Statement
前提条件:
1 使用连接池
2 使用了spring的ioc,即DAO是单例的
提出这个问题是由于我们系统中的实际出现的状况
由于开发人员众多,素质参差不齐,开发时间紧迫,
出现了大量的不符合规范的代码以及错误代码.
常见的就是 在关闭链接的时候没有关闭链接的创建的所有的Statement
(关闭了部分,但不是所有)
所以想和 大家探讨一下该如何在代码层次实现关闭数据库链接时,自动关闭由该链接创建的所有的Statement.
我的思路是这样的
将"当前线程+当前链接"创建的所有Statement 放入一个ThreadLocal 对象内.
当关闭链接时, 从ThreadLocal 对象取出 所有的 Statement ,逐个关闭.
不知道这样的思路是否可行.
下面附上代码:
为了阅读方便没有写出全部的创建Statement的方法
在dao内的getConnection时 可以这么写
关闭Connection时 可以这么写
要创建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());
以上只是我的一些思路,虽然在本机测试是可以的,但是不知道到底实际上是否可行
还请看看 谢谢了
评论
poiuyt373
2007-07-12
楼上才是正解,原有代码不做任何修改;
出现这种问题,spring完全没有用好。
出现这种问题,spring完全没有用好。
leadyu
2007-07-12
建议不要这样,这样的话维护较为困难,我的方法是代理连接池,spring也可采用第三方数据源,写个connection代理,new YouCnnection(Connection delegate).这样对于系统是透明的,默默地把资源回收了
代理里面想解决关闭statement的事,不用说大家也知道怎么做了吧。
代理里面想解决关闭statement的事,不用说大家也知道怎么做了吧。
huangpengxiao
2007-04-26
在连接池情况下,也是被close()之后才可以分配给其他线程的
确定?
确定?
fins
2007-04-22
谢谢 你解开了我一大疑问啊
我对池的一些知识确实很匮乏 谢谢指点
"在连接池情况下,也是被close()之后才可以分配给其他线程的"
这句话正是我想知道的 谢谢
我对池的一些知识确实很匮乏 谢谢指点
"在连接池情况下,也是被close()之后才可以分配给其他线程的"
这句话正是我想知道的 谢谢
Lucas Lee
2007-04-21
fins 写道
所以我真正想问的是
" 使用 ThreadLocal对象记录 当前conn在当前线程内打开的所有的Statement.
这样的思路可以不 "??
我觉得这样没有什么问题。
但我不觉得应该用ThreadLocal来记录,一个Connection应该只给一个线程使用(在连接池情况下,也是被close()之后才可以分配给其他线程的。),所以用一般的容器类存放所有此连接上打开的Statement就可以了,在connection.close()时,调用容器中所有的Statement.close(),并清空容器。
fins
2007-04-21
Lucas Lee 写道
既然这样的话,我也觉得包装Connection,然后delegate到实际的Connection上,除了在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来;等Connection.close()时,调用所有Statement.close()。
可能是我没说明白
我知道这种方式可以 也知道是最好的实现方式
但我的核心问题就是
"在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来"
那么怎么记录? 你不能记录当前链接打开的所有的的Statement,因为这样是不安全的吧 因为使用了池,会出现关闭不想关闭的Statement的情况.
所以我真正想问的是
" 使用 ThreadLocal对象记录 当前conn在当前线程内打开的所有的Statement.
这样的思路可以不 "??
而不是该使用什么样的模式来实现这个功能
likeblood
2007-04-20
6楼正解
Lucas Lee
2007-04-20
既然这样的话,我也觉得包装Connection,然后delegate到实际的Connection上,除了在prepareStatement,createStatement等方法上做一些处理,将Statement对象记录下来;等Connection.close()时,调用所有Statement.close()。
spiritfrog
2007-04-20
codeutil 写道
自己实现一下 java.sql.Connection等接口,把原来的connection包装一下就可以了阿.
以楼主项目的情况来看,有那么多的dao类要进行最小范围的重构,这样的办法应该是不错的。
另外楼主的方法应该也可行,只是增加了些代码量
hpq852
2007-04-19
装饰模式的经典场景.
另外好的连接池在回收Connection的时候会自动关闭ResultSet 和 Statement 的
另外好的连接池在回收Connection的时候会自动关闭ResultSet 和 Statement 的
codeutil
2007-04-19
自己实现一下 java.sql.Connection等接口,把原来的connection包装一下就可以了阿.
fins
2007-04-19
其实这些我知道
但是现在的前提是 系统已经开发完成
一共有2000多个dao 都使用了传统的方式
在进行最小的重构前提下,我在顶楼里提出的那种思路和方案是否可行呢
但是现在的前提是 系统已经开发完成
一共有2000多个dao 都使用了传统的方式
在进行最小的重构前提下,我在顶楼里提出的那种思路和方案是否可行呢
realreal2000
2007-04-19
使用jdbcTemplete是不错的办法,推广它的时间和培训时间应该不是难么难吧
fins
2007-04-19
楼上的有些高估我们的开发所采用的技术了
我们dao里就是要操作那些基本的 connection statement resultset
在这个前提下有什么办法呢 我也很无奈
如果想从源头解决问题 那就是所有开发人员提高个人职业修养和素质
否则什么都没用
我们dao里就是要操作那些基本的 connection statement resultset
在这个前提下有什么办法呢 我也很无奈
如果想从源头解决问题 那就是所有开发人员提高个人职业修养和素质
否则什么都没用
Lucas Lee
2007-04-19
这种方法不在源头解决,我看以后维护可能比较麻烦。
源头上统一使用一些jdbcTemplete方法避免直接管理connection和statement不就可以了?
源头上统一使用一些jdbcTemplete方法避免直接管理connection和statement不就可以了?
- 浏览: 743348 次
- 性别:

- 来自: 小胖儿的大城

- 详细资料
搜索本博客
我的相册
customHead
共 76 张
共 76 张
链接
最新评论
-
再发一篇牢骚贴: 文档又丢 ...
文档也是要入CVS的。
-- by bottom -
GT-Grid开发笔记: 这几天 ...
惊鸿逝水 写道>>关于价值,如果GT收费,那么它值多少钱呢? 10元吧 10 ...
-- by lonelyblue -
蝙蝠侠6票房过$2亿之后的 ...
强烈鄙视 剧透的人 尤其是 剧透之前 不写明"剧透 慎入"的人 这电影在我心里 ...
-- by fins -
蝙蝠侠6票房过$2亿之后的 ...
看了。。感想: --BATMAN如果不是有超强的装备,一定是JOKER笑到最后。 ...
-- by dimvar -
GT-Grid "缺陷,、bug、 ...
问题不是出在这 你等着新版本吧 一个属性搞定 :) 今天晚上发布 (前提是 ...
-- by fins






评论排行榜