java jdbc不允许任何操作

java jdbc不允许任何操作,java,jdbc,Java,Jdbc,我得到一个语句关闭后不允许进行任何操作。-非常明显,也不言自明 至于我的代码是怎么回事。在任何情况下,我想知道我如何能做到这一点在一个干净的方式 public class BaseClass { Connection con; Statement st; protected void establishDBConnection() throws ClassNotFoundException, SQLException { Class.forN

我得到一个
语句关闭后不允许进行任何操作。
-非常明显,也不言自明 至于我的代码是怎么回事。在任何情况下,我想知道我如何能做到这一点在一个干净的方式

public class BaseClass {
    Connection con;
    Statement st;

    protected void establishDBConnection() throws ClassNotFoundException,
      SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        String cString = "....";
        con = DriverManager.getConnection(cString, user, password);
        st = con.createStatement();
    }

    public BaseClass() {
        try {
            createDBConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


public ClassB extends BaseClass {

    public ClassB() {
        super();
    }

    public void doSomething() {
        try {
            String q = "select * from my_table";
            String moreQuery = "update my_table ...."
            String anotherQuery = "do something fancy..."
            rs = st.executeQuery(q);
            while (rs.next()) {
                st.executeUpdate(moreQuery);
                st.executeUpdate(anotherQuery);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Error in getAllAssociatesOfMra: " + e);
        }
    }
}
当前我的代码正在抛出一个
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:语句关闭后不允许执行任何操作。
关于发生了什么,例外是显而易见的,但我想知道如何处理基类中的结束

更新
我知道有几个像我这样的相关问题。这些问题的唯一问题是所有的事情都是在主课上完成的。认为这是一种设计/抽象问题

< P>你的设计不好。您最好从连接池获取连接,在
doSomething()
方法的开头创建语句(例如调用超类方法),然后在完成“某事”后关闭
语句
结果集
.

如果我理解您的问题和目标,您将需要在
doSomething()
中创建多个语句对象,并且您需要在finally块中清理语句和结果集,如-

Statement st = con.createStatement();
String q = "select * from my_table";
String moreQuery = "update my_table ....";
String anotherQuery = "do something fancy...";
ResultSet rs = st.executeQuery(q);

try {
    while (rs.next()) {
        Statement stmt = null;
        try {
            stmt = con.createStatement();
            stmt.executeUpdate(moreQuery);
        } finally {
            if (stmt != null) {
                stmt.close();
            }
        }
        try {
            stmt = con.createStatement();
            stmt.executeUpdate(anotherQuery);
        } finally {
            if (stmt != null) {
                stmt.close();
            }
        }
    }
} finally {
    if (rs != null) {
        rs.close();
    }
    if (st != null) {
        st.close();
    }
}
我提出几点建议:

  • 使用连接池设计
  • 要防止语句关闭,可以使用
    finally
    块关闭它们
  • 因为在另一个查询之后有一个查询,所以使用(提交/回滚)来防止事情“半途而废”

在你做出一个好的设计之前,你必须了解你想要实现的目标。因此,我想为此制定一些目标,然后看看设计如何满足这些目标。为了实现这一目标,让我们来看一下数据库连接是如何工作的

数据库是一个独立的进程,它可以在同一台机器上,也可以在通过网络访问的另一台机器上。网络连接可能会因瞬态条件、数据库停机等而过时。即使数据库位于同一台计算机上,并且网络不是问题,但让应用程序依赖于单独进程的状态而无法恢复仍然是一种不好的形式,这意味着,如果数据库宕机,应用程序无法自行恢复,则必须重新启动它

连接的某些属性:

  • 它们需要一段时间来初始化,足够长的时间你不会想为每个用户请求创建一个新的。(如果数据库在同一台机器上,这几乎不会是一个大问题。)

  • 它们的数量有限,您不希望一个用户请求占用的时间超过需要的时间,因为这将限制可以同时连接的其他用户的数量

  • 在数据库连接对象上有一个提交方法,允许您将操作分组到事务中,以便a)您的查询具有一致的数据视图,b)以全有或全无的方式应用操作(如果操作失败,您不会有一半的操作将数据库弄得乱七八糟,您必须撤消)。当前,您的连接处于自动提交模式,这意味着每个操作都是单独提交的(并且您不能将操作分组在一起)

  • 它们是同步的,因此一次只有一个线程可以使用它们。这样,多个用户就不会破坏彼此的工作,但如果您只有一个连接,您的应用程序将无法扩展,因为每个用户都在排队等待连接

从所有这些中,我们可以得出一些设计目标。一个是,我们希望能够重新初始化可能出错的数据库连接,我们希望有多个连接可用,这样每个人都不会等待同一个连接,我们希望将连接与用户请求关联,这样我们就可以将给定用户的操作分组到事务中

很难说你发布的代码到底做了什么,因为它取决于对象的范围,而这个问题没有明确说明。如果这些对象是根据用户请求创建的,那么每次都会得到一个新的连接,这解决了陈旧性问题,但速度可能较慢。为每个表使用不同的连接可能会使速度变得更慢,不必要地限制应用程序的并发性,并且不允许对不同表上的操作进行分组的事务,因为您没有公共连接对象来调用commit。连接是如何关闭的并不明显;对他们来说,被遗弃到超时是浪费时间的

一种常用的替代方法是将数据库连接汇集在一起(池可以测试数据库连接并替换过时的连接),然后将它们分发给用户请求,在请求完成时将它们返回到池中(池可以将连接包装在对象中,对其调用close将其返回到池中)。同时,用户线程可以在连接上执行操作,创建自己的语句并在退出时关闭它们,然后提交结果

它遵循上述方法(除了具有更多功能)。有些人不喜欢过于复杂的框架,但我建议至少看看Spring的例子。这样,您就知道了另一种可行的方法来组织代码,您可以改进自己的设计。

如果这是一个设计/抽象问题,那么它应该在,不是吗?