java多线程访问数据库的问题

boodweb 2005-06-09 10:57:16

大家知道一般写数据库的程序的话都会写一个数据库层来分离隐藏数据库操作

但是这里我一直有一点想不大通,比如你的数据库层提供了一个接口getName返回某数据项的Name属性

那么代码一般应该这样(简化的代码)

getName(..)
{
//这里整个数据库层公用一个stmt
stmt.execute("sql");
rs = stmt.getResultSet();
name = rs.getString(1);
return name;
}

这里我们发现如果整个数据库层共用一个stmt的话在多线程程序中就会产生问题,譬如执行到execute以后另一个线程调用了另一个获取属性的函数,比如getAge,那么getResultSet就会返回不同的结果,造成错误

然而如果每次都createStatement的话却似乎无法关闭stmt,因为getString得到的结果还要到外面的应用层使用,而java都是传引用的,如果关闭了stmt这个返回的String是不是还会有效呢?不知道createStatement造成的资源消耗到底如何

不知道大家都是怎么解决这个问题的,谢谢!
...全文
816 点赞 收藏 14
写回复
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
boodweb 2005-06-10
恩,懂你的意思了,就是用连接池来避免重复连接
谢谢大家了
回复
fashchina 2005-06-10
你的问题,就是说多线程共用stmt对象,会出现一个问题

那么,就这么做,不共用这个stmt对象,一个DAO封装对数据库的操作
public class DocBaseMan{
Context ctx=null;
DataSource ds=null;
SysLog log=null;
ChangeEncoding ce=null;
//构造函数
public DocBaseMan(){
//从连接池中获取数据库连接
try{
ctx=new InitialContext();
ds=(DataSource)ctx.lookup("documents");
}
catch(NamingException e){
e.printStackTrace();
}
//建立一个日志类的实例
log=new SysLog();
ce=new ChangeEncoding();
}
public String getAdminOfDocBase(String name)
{
Connection con = null;
PreparedStatement ps = null;
ResultSet rs=null;
String admin="";
try{
String strQuery = "select admin from docBase where name=?";
con = ds.getConnection();//从连接池获得连接
ps = con.prepareStatement(strQuery);
ps.setString(1,ce.changeCharset(name));
rs=ps.executeQuery();
if(rs.next())
admin=rs.getString("admin")
}
catch(SQLException e){
e.printStackTrace();
}
finally{
if (rs != null) try {rs.close();}
catch (SQLException ignore) {}
if (ps != null) try {ps.close();}
catch (SQLException ignore) {}
if (con != null) try {con.close();}
catch (SQLException ignore) {}
}
return admin;
}
}

这样,就不会出现多线程中的并发问题

因为,conn stmt rs都是局部变量

数据可以放在一个VO里,或者集合数组字符串中

这样,数据层的代码就不会出现这表现层了,在表现层就是数据传输对象在传值
回复
reelcol 2005-06-09
用synchronized(同步)来修饰你得方法,这样可以有效得防止冲突,因为

在任何时刻,只会有一个线程得特定对象来调用synchronized方法(不管这个线程有多少synchronized方法),java同步机智,有一个对象调用了synchronized方法,这个对象就会被锁定,这个锁定时java内部处理得,不用自己写代码,是不是很爽,java就是把所有得东西都给你写好放在那里,这是java得优点,也是java得缺点,java让程序员变得巨懒无比啊!!!

synchronized修饰 (eg.):
public synchronized void a(){

}
回复
stray1718 2005-06-09
synchronized
回复
hh410 2005-06-09
我是用DAO封装,即用一个JAVA类封装数据(或BEAN),然后每次传一条数据,不单独传字段。就不会存在这种问题啦。
回复
zmfox 2005-06-09
Please set stem is null firstly, when you excute a new query. Then redefine the stem object. Have a try.
回复
boodweb 2005-06-09
to yxhzj:
呵呵,就是不明白机制才来问的啊
可否把机制说的详细些?
回复
fashchina 2005-06-09
to GJA106(中文字符):
如果在stmt.close之前getString,那这个String在stmt.close之后还有效么?
您说的自己封装数据是什么意思?



怎么会没效果,
你把数据放在其他的里面,比如,数组等集合中,怎么会无效

机制可要明白哦
回复
Maple99 2005-06-09
多线程问题一定要考虑同步的问题,楼上所说的问题的出现是一定的。
回复
huanghelang 2005-06-09
如果在stmt.close之前getString,那这个String在stmt.close之后,只要这个String还没有丢弃,应该都是有效的
回复
boodweb 2005-06-09

to GJA106(中文字符):
如果在stmt.close之前getString,那这个String在stmt.close之后还有效么?
您说的自己封装数据是什么意思?
回复
GJA106 2005-06-09

1.没有必要在数据库层共用一个stmt,而是共用一个Connection.
共用一个stmt,应该在一个"线程"中使用而且对stmt操作不会太久.

2.每次都createStatement应该马上关闭stmt.当然无法再实行getString.楼主可以自己封装数据-->关闭stmt-->返回调用者

3.多线程操作,同意 reelcol(reelcol).

回复
cy5and9 2005-06-09
数据库DBMS中就已经处理了这个问题(不需要我们去写代码),在java中synchronized修饰你可以锁定对象,让指定得程序代码执行时不受干扰。
不过我建议数据库开发时少用线程,线程很占用系统资源的。
回复
MARS.nEIL 2005-06-09
学习。。
回复
发动态
发帖子
Web 开发
创建于2007-09-28

7.9w+

社区成员

Java Web 开发
申请成为版主
社区公告
暂无公告