关于JDBC中No operations allowed after connection closed的问题

xiaofc9 2010-11-11 09:22:33

public static Operater check(String name, String password) {
Operater operater=new Operater();//操作员信息对象
String sql = "select * from tb_operator where name='" + name
+ "' and password='" + password + "'and admin=1";//查询字符串
ResultSet rs = Dao.executeQuery(sql);//执行查询
try {
while (rs.next()) {//如果查询到了记录
operater.setId(rs.getString("id"));//设置操作员编号
operater.setName(rs.getString("name"));//设置操作员用户名
operater.setGrade(rs.getString("admin"));//设置操作员等级
operater.setPassword(rs.getString("password"));//设置管理员密码
}
} catch (Exception e) {
e.printStackTrace();
}
Dao.close(); //关闭连接对象
return operater;//返回操作员信息对象
}


第一次调用此方法没问题 可第二次就出现下面的问题

com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException:
No operations allowed after connection closed

这个问题怎么解决啊 只有把Dao.close();这个关闭Connection的方法去掉,可是这样好像也不对啊?
各位有没有碰到过类似的问题,有好的解决办法?
...全文
55701 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
front2010 2011-12-11
  • 打赏
  • 举报
回复 1
Mysql的数据库连接默认等待时限(wait_timeout)是8个小时,在该时限内如果没有使用该Connection(超过了这个时限),Connection就会被关闭。虽然该Connection已经被关闭,但Connection不为空。第一次调用时没有问题的,如果长时间没有使用该Connection,Connection会被Mysql关闭(但不为null)。此时调用该Connection时就会抛出异常com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed by the driver.
如果一个程序中使用一个共同的static的Connection时,这种问题就很容易出现。

查看Mysql的默认wait_timeout值(以下是我的Mysql中的配置)
show variables like '%timeout%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| connect_timeout | 10 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 6000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| table_lock_wait_timeout | 50 |
| wait_timeout | 6000 |
+----------------------------+-------+
10 rows in set (0.00 sec)

wait_timeout的值是6000秒。


解决方法:
1.修改Mysql的配置文件,添加一个属性,一旦Connection被自动关闭,便进行自动重连
2.在程序中进行判断,如hemowolf的方式。
3.使用更高级的数据库连接的jar,老的都会有这种问题。
4.不直接使用jdbc,改用Spring中的jdbcTemplate。
a308313845 2011-07-12
  • 打赏
  • 举报
回复
哎,我也遇到这样问题,纠结中
「已注销」 2010-11-12
  • 打赏
  • 举报
回复
异常信息很明确了,你都关闭了链接,就不能再进行操作了
就如你说的那样,不要调用close方法
zhouyong0 2010-11-12
  • 打赏
  • 举报
回复
我没有发现楼主的代码有什么问题,可能有哪个地方没有看到
1.在close以后连接是被关闭了,但是它也把connection设置为null了
2.当调用executeQuery时 发现connection为空它有会新建一个connection
我这边执行了2次都没有问题 代码如下


public class Test {
protected static String dbClassName =
"com.mysql.jdbc.Driver";//数据库连接驱动类
protected static String dbUrl = "jdbc:mysql://localhost:3306/ssh";//数据库连接URL
protected static String dbUser = "root"; //数据库用户名
protected static String dbPwd = ""; //数据库密码
private static Connection conn = null; //数据库连接对象
private Test() { //默认构造函数
try {
if (conn == null) { //如果连接对象为空
Class.forName(dbClassName); //加载驱动类
conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);//获得连接对象
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
private static ResultSet executeQuery(String sql) { //查询方法
try {
if(conn==null) new Test(); //如果连接对象为空,则重新调用构造方法
return conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE).executeQuery(sql);//执行查询
} catch (SQLException e) {
e.printStackTrace();
return null; //返回null值
} finally {
}
}
private static int executeUpdate(String sql) { //更新方法
try {
if(conn==null) new Test(); //如果连接对象为空,则重新调用构造方法
return conn.createStatement().executeUpdate(sql);//执行更新
} catch (SQLException e) {
e.printStackTrace();
return -1;
} finally {
}
}
public static void close() {//关闭方法
try {
conn.close();//关闭连接对象
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null; //设置连接对象为null值
}
}

public static void main(String[] args){
run();
run();

}
public static void run(){
ResultSet rs = Test.executeQuery("select * from user");
try {
rs.next();
System.out.println(rs.getString(1));
} catch (SQLException e) {
e.printStackTrace();
}
Test.close();
}

}
dickli1986 2010-11-12
  • 打赏
  • 举报
回复
ResultSet rs = Dao.executeQuery(sql);//执行查询
楼主直接用Dao就不对了哦,你要先new一个Dao的实例,然后再调用实例的executeQuery()方法哦,否则执行完close,就没法创建Dao了
leafandy 2010-11-12
  • 打赏
  • 举报
回复
注释不需要每行都写吧?
小灰狼 2010-11-12
  • 打赏
  • 举报
回复
try this:

if(conn==null) new Dao();
===>>>>>
if(conn == null || conn.isClosed()) new Dao();

=================================================
题外话

楼主的DAO类写得不怎么合理,其实DAO模式不是提供静态方法,而是使用实例方法

dao 中的 Connection conn 是静态的。楼主这样做如果是开发 AWT/Swing 类型的系统可能问题不大,但是如果是写jsp/servlet 这类网站这种多线程系统,一定会出问题。
酒剑仙 2010-11-12
  • 打赏
  • 举报
回复
楼主是个好孩子!
小灰狼 2010-11-12
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 huang005x 的回复:]
楼主的注释写得真多, 学习
[/Quote]

注释多了,但是也滥了
youjianbo_han_87 2010-11-12
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 xiaochun91103 的回复:]

原因很简单。在对数据库操作结束后关闭连接是正确的做法,没什么大问题。至于出现:No operations allowed after connection closed。这样的问题原因只有一个,你这里和数据库的连接Connection是一个Static的,程序共享这一个Connection。所以第一次对数据库操作没问题,当把Connection关闭后,第二次还想操作数据库时Connection肯……
[/Quote]

正解。。。

CSDN的这个回复编辑器也太他妈比的烂了。。。
风影枫林 2010-11-12
  • 打赏
  • 举报
回复
楼主的注释写得真多, 学习
xiaochun91103 2010-11-12
  • 打赏
  • 举报
回复
原因很简单。在对数据库操作结束后关闭连接是正确的做法,没什么大问题。至于出现:No operations allowed after connection closed。这样的问题原因只有一个,你这里和数据库的连接Connection是一个Static的,程序共享这一个Connection。所以第一次对数据库操作没问题,当把Connection关闭后,第二次还想操作数据库时Connection肯定不存在了。
o2cola 2010-11-12
  • 打赏
  • 举报
回复
全部调用之后再close么,查询操作和关闭connection操作分开比较好,
xiaofc9 2010-11-11
  • 打赏
  • 举报
回复
源码在这
public class Dao {
protected static String dbClassName =
"com.mysql.jdbc.Driver";//数据库连接驱动类
protected static String dbUrl = "jdbc:mysql://localhost/db_library;";//数据库连接URL
protected static String dbUser = "root"; //数据库用户名
protected static String dbPwd = "admin"; //数据库密码
private static Connection conn = null; //数据库连接对象
private Dao() { //默认构造函数
try {
if (conn == null) { //如果连接对象为空
Class.forName(dbClassName); //加载驱动类
conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);//获得连接对象
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
private static ResultSet executeQuery(String sql) { //查询方法
try {
if(conn==null) new Dao(); //如果连接对象为空,则重新调用构造方法
return conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE).executeQuery(sql);//执行查询
} catch (SQLException e) {
e.printStackTrace();
return null; //返回null值
} finally {
}
}
private static int executeUpdate(String sql) { //更新方法
try {
if(conn==null) new Dao(); //如果连接对象为空,则重新调用构造方法
return conn.createStatement().executeUpdate(sql);//执行更新
} catch (SQLException e) {
e.printStackTrace();
return -1;
} finally {
}
}
public static void close() {//关闭方法
try {
conn.close();//关闭连接对象
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null; //设置连接对象为null值
}
}
/*
* 管理员登录方法
*/
public static Operater check(String name, String password) {
Operater operater=new Operater();//操作员信息对象
String sql = "select * from tb_operator where name='" + name
+ "' and password='" + password + "'and admin=1";//查询字符串
ResultSet rs = Dao.executeQuery(sql);//执行查询
try {
while (rs.next()) {//如果查询到了记录
operater.setId(rs.getString("id"));//设置操作员编号
operater.setName(rs.getString("name"));//设置操作员用户名
operater.setGrade(rs.getString("admin"));//设置操作员等级
operater.setPassword(rs.getString("password"));//设置管理员密码
}
} catch (Exception e) {
e.printStackTrace();
}
Dao.close(); //关闭连接对象
return operater;//返回操作员信息对象
}
}
若鱼1919 2010-11-11
  • 打赏
  • 举报
回复
这种问题只能查看Dao的源码才知道怎么回事

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧