【问题标题】:How to fix com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed. exception?如何修复 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:连接关闭后不允许操作。例外?
【发布时间】:2015-01-12 19:03:04
【问题描述】:

这是我保存记录的查询。


public void saveTotal(JTextField txtGtotal, JTextField txtPTotal) {
    try {
        ResultSet rs = JDBC.getData("select MAX(or_id) as or_id from `order`");
        if (rs.first()) {
            if (rs.getInt("or_id") > 0) {
                try {
                    String date1 = new Validation().today();
                    boolean b1 = JDBC.putData("insert into transaction(tr_date, amount, tr_type) values ('" + date1 + "' , '" + txtGtotal.getText() + "' , 'order')");
                    if (b1) {
                        try {
                            ResultSet rs1 = JDBC.getData("select MAX(tr_id) as tr_id from transaction");
                            if (rs1.first()) {
                                try {
                                    boolean b2 = JDBC.putData("insert into transaction(tr_date, amount, tr_type) values ('" + date1 + "' , '" + txtPTotal.getText() + "' , 'profit')");
                                    if (b2) {
                                        try {
                                            ResultSet rs2 = JDBC.getData("select MAX(tr_id) as tr_id from transaction");
                                            if (rs2.first()) {

                                                try {
                                                    boolean b3 = JDBC.putData("insert into o_de(or_id, tr_id, oday, gtotal) values ('" + rs.getInt("or_id") + "' , '" + rs1.getInt("tr_id") + "','" + date1 + "','" + txtGtotal.getText() + "' )");
                                                    if (b3) {
                                                        try {
                                                            boolean b4 = JDBC.putData("insert into order_profit(or_id, tr_id, ptotal) values ('" + rs.getInt("or_id") + "' , '" + rs1.getInt("tr_id") + "','" + txtPTotal.getText() + "' )");
                                                            if (b4) {
                                                                JDBC.commit();
                                                                JOptionPane.showMessageDialog(null, "Order Saved Sucessfully..");
                                                                JDBC.putClose();
                                                                JDBC.conClose();

                                                            }
                                                        } catch (Exception e) {
                                                            JDBC.rollback();
                                                            e.printStackTrace();
                                                        } finally {
                                                            JDBC.putClear();
                                                            JDBC.conClear();
                                                        }
                                                    }
                                                } catch (Exception e) {
                                                    e.printStackTrace();
                                                }

                                            }

                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                } catch (Exception e) {
                                    JDBC.rollback();
                                    e.printStackTrace();
                                }
                            }
                        } catch (Exception e) {
                            JDBC.rollback();
                            e.printStackTrace();
                        }

                    }
                } catch (Exception e) {
                    JDBC.rollback();
                    e.printStackTrace();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}


这是我的 JDBC 类。

     package Modle;

  import java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.util.logging.Level;
  import java.util.logging.Logger;

  public class JDBC {

static Connection con = null;
static boolean b;
static PreparedStatement state;

public static void setCon() {
    try {
        Class.forName("com.mysql.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/lottery", "root", "123");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public static Connection getCon() throws Exception {
    if (con == null) {
        setCon();
    }
    return con;
}

public static boolean putData(String sql) {
    try {
        getCon().setAutoCommit(false);
        state = getCon().prepareStatement(sql);
        state.executeUpdate();
        b = true;
    } catch (Exception e) {
        e.printStackTrace();
        b = false;
    }
    return b;
}

// connection commit
public static void commit() {
    try {
        con.commit();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

  // rollback data
  public static void rollback() {
    if (con != null) {
        try {
            con.rollback();
        } catch (SQLException ex) {
            Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

// close statement
public static void putClose() {
    try {
        state.close();
    } catch (SQLException ex) {
        Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
    }
}
 // close connection

  public static void conClose() {
    try {
        con.setAutoCommit(true);
        con.close();
    } catch (SQLException ex) {
        Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
    }
}

// clear prepared statement
public static void putClear() {
    try {
        if (state != null && !state.isClosed()) {
            state.close();
        }
    } catch (SQLException ex) {
        Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
    }
}

// clear the connection
public static void conClear() {
    try {
        if (con != null && !con.isClosed()) {
            con.setAutoCommit(true);
            con.close();
        }
    } catch (SQLException ex) {
        Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public static ResultSet getData(String sql) throws Exception {
    Statement state = getCon().createStatement();
    ResultSet rs = state.executeQuery(sql);
    return rs;
 }
 }


这是我第一次尝试在 mysql 中进行事务处理。我知道这不是借口。但是我对这种连接处理只有一个粗略的想法。如果我的代码不完善,请给我一个演示答案。


如何解决此连接关闭后不允许操作异常?谢谢。


也添加了堆栈跟踪。我认为还有另外 2 个地方也发现了同样的错误。他们是在运行此查询之前来的。

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed    after connection closed.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1206)
at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1198)
at com.mysql.jdbc.ConnectionImpl.createStatement(ConnectionImpl.java:2484)
at com.mysql.jdbc.ConnectionImpl.createStatement(ConnectionImpl.java:2466)
at Modle.JDBC.getData(JDBC.java:115)
at Controler.NewOrderCon2.saveTotal(NewOrderCon2.java:196)
at lottery.NewOrder.jButton6ActionPerformed(NewOrder.java:2350)
at lottery.NewOrder.access$1200(NewOrder.java:28)
at lottery.NewOrder$13.actionPerformed(NewOrder.java:537)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6505)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:688)
at java.awt.EventQueue$3.run(EventQueue.java:686)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:702)
at java.awt.EventQueue$4.run(EventQueue.java:700)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

【问题讨论】:

  • “try-catch's”的母亲......它发生在哪一行?发布完整的堆栈跟踪。
  • :D 添加到问题中.. @Branislav Lazic

标签: java mysql jdbc transactions


【解决方案1】:

您是否知道您实际上是从 GUI 中访问后端这一事实?您正在将参数从文本字段直接传递到您的数据库。这是主要搞砸的来源。至少验证您的输入,否则Little Bobby Tables 会提前终止您的工作合同。

至于您的错误:对不起,但此代码需要进行重大重构。仅按行数,这段代码就做得太多了。第一条黄金法则:保持你的方法简短。第二条黄金法则:让它们更短。

您自己不了解正在发生的事情这一事实对您来说是一个大红灯,表明您需要重新考虑您的设计。

  • 使用 JDBC.putData() 使编写内容的方法独立。
  • 对 JDBC.getData() 执行相同操作。
  • 看到正在出现的模式。

我猜这是对 JDBC 中 connection.close() 的过早调用。通过将您的操作分解为更原子的操作,您可以更好地推理您的代码,从而了解手头的错误。

很抱歉没有提供解决方案,但从长远来看,坚持一些代码原则会更好。学习他们!越早越好,因为我需要更多的业力: 阅读 Robert C. Martin 的“清洁代码”。 http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

然后您将走上启蒙之路,从而使用 DAOFactory(提示)和 DAO 设计模式(也提示)并成为编码之神。恭喜!

好吧,这里有一个关于重构外观的小指南。未完成且未经测试,我想我搞砸了 SQL 插入序列(不知道在哪里使用了哪个 transactionId)。但我希望你能有所了解。 祝您有美好的一天,欢迎来到牙买加!

package mysqlfix;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTextField;

public class JDBC {

    static Connection con = null;
    static boolean b;
    static PreparedStatement state;

    public static void setCon() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/lottery", "root", "123");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static Connection getCon() throws Exception {
        if (con == null) {
            setCon();
        }
        return con;
    }

    public static boolean putData(String sql) {
        try {
            getCon().setAutoCommit(false);
            state = getCon().prepareStatement(sql);
            state.executeUpdate();
            getCon().commit();
            b = true;
        } catch (Exception e) {
            e.printStackTrace();
            b = false;
        }
        return b;
    }

// connection commit
    public static void commit() {
        try {
            con.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // rollback data
    public static void rollback() {
        if (con != null) {
            try {
                con.rollback();
            } catch (SQLException ex) {
                Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

// close statement
    public static void putClose() {
        try {
            state.close();
        } catch (SQLException ex) {
            Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    // close connection

    public static void conClose() {
        try {
            con.setAutoCommit(true);
            con.close();
        } catch (SQLException ex) {
            Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

// clear prepared statement
    public static void putClear() {
        try {
            if (state != null && !state.isClosed()) {
                state.close();
            }
        } catch (SQLException ex) {
            Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

// clear the connection
    public static void conClear() {
        try {
            if (con != null && !con.isClosed()) {
                con.setAutoCommit(true);
                con.close();
            }
        } catch (SQLException ex) {
            Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static ResultSet getData(String sql) throws Exception {
        Statement state = getCon().createStatement();
        ResultSet rs = state.executeQuery(sql);
        return rs;
    }

    public void saveTotal(JTextField txtGtotal, JTextField txtPTotal) {
        SuperDAO superDAO = new SuperDAO();

        if (superDAO.getMaxIdFromOrder() > 0) {
            Date date1;
            date1 = new Date();
            String txtGTotalFromTextField = txtGtotal.getText();
            String txtPTotalFromTextField = txtPTotal.getText();
            boolean b1 = false;
                    //regarding the transaction id...
            //this changes whilst updating the table transaction.

            int transactionId = -1;
            if (txtGTotalFromTextField.matches("[a-zA-Z]")) {
                transactionId = superDAO.insertOrderIntoTransaction(date1, txtGTotalFromTextField);
                //b1 = JDBC.putData("insert into transaction(tr_date, amount, tr_type) values ('" + date1 + "' , '" + txtGTotalFromTextField + "' , 'order')");
            }
            if (transactionId > 0) {
                try {
                } catch (Exception ex) {
                    Logger.getLogger(JDBC.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (txtPTotalFromTextField.matches("[a-zA-Z]")) {
                    transactionId = superDAO.insertProfitIntoTransaction(date1, txtGTotalFromTextField);
                }
                JDBC.putData("insert into o_de(or_id, tr_id, oday, gtotal) values ('" + superDAO.getMaxIdFromOrder() + "' , '" + transactionId + "','" + date1 + "','" + txtGtotal.getText() + "' )");
                JDBC.putData("insert into order_profit(or_id, tr_id, ptotal) values ('" + superDAO.getMaxIdFromOrder() + "' , '" + transactionId + "','" + txtPTotal.getText() + "' )");

                                                        //JDBC.commit();
                //JOptionPane.showMessageDialog(null, "Order Saved Sucessfully..");
                JDBC.putClose();
                JDBC.conClose();

            }

        }

    }

}



package mysqlfix;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author edm
 */
public class SuperDAO {

    Connection conn;

    public SuperDAO() {
        try {
            this.conn = JDBC.getCon();
        } catch (Exception ex) {
            Logger.getLogger(SuperDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int getMaxIdFromOrder() {

        try {
            ResultSet rs = JDBC.getData("select MAX(or_id) as or_id from `order`");
            if (rs.first()) {

                return rs.getInt("or_id");
            }
        } catch (SQLException ex) {
            Logger.getLogger(SuperDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(SuperDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }

    public int getMaxIdFromTransaction() {
        ResultSet rs;
        try {
            rs = JDBC.getData("select MAX(tr_id) as tr_id from transaction");
            if (rs.first()) {
            return rs.getInt("tr_id");
        }
        } catch (Exception ex) {
            Logger.getLogger(SuperDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }


    public int insertOrderIntoTransaction(Date date, String text) {
        JDBC.putData("insert into transaction(tr_date, amount, tr_type) values ('" + date + "' , '" + text + "' , 'order')");
        return getMaxIdFromTransaction();
    }

     public int insertProfitIntoTransaction(Date date, String text) {
        JDBC.putData("insert into transaction(tr_date, amount, tr_type) values ('" + date + "' , '" + text + "' , 'profit')"); 

        return getMaxIdFromTransaction();
    }



}

当然,旅程并不止于此。我没有完成 JDBC saveTotal()。我刚开始,剩下的交给你。

请注意,我没有针对数据库测试此代码(某些 sql ddl 文件丢失)。另外,我没有使用回滚机制。此外, saveTotal() 存在于它不属于的 JDBC 中。在您的 GUI 中使用 saveTotal(如果需要),让所有数据库访问都通过 SuperDAO。这不是最好的设计,但它不是太抽象,您可以轻松地看到关注点分离如何使您的代码更具可读性和可维护性。

【讨论】:

  • :D 谢谢.. 我什至不知道笑还是哭.. :D 但是为了澄清你的意思是这样的..prepareStatementInsert = dbConnection.prepareStatement(insertTableSQL); PreparedStatementInsert.setInt(1, 999); PreparedStatementInsert.setString(2, "mkyong101"); PreparedStatementInsert.setString(3, "system");准备好的StatementInsert.executeUpdate();
  • 如果你能给我你真正说的话,我会欠你一顿饭。谢谢你。
  • 当然笑 ;-) 但是如果这段代码投入生产,你会哭的,半年后你必须修复错误。请把我的帖子看作是来自专业开发人员(还没有资深)的智慧。我在你所在的地方。只是就什么使我的代码更稳定提供建议。你很快就会到达那里◕ᴥ◕
  • 至于您的第一条评论:是的,验证输入字符串,然后使用 PreparedStatement 将其注入您的查询。如果您的输入字段仅包含字母,则验证数据库的输入是否遵循这些规则。正则表达式有很大帮助:要检查字符串是否仅包含字母,请使用:"aagbvcfdfg".matches("[a-zA-Z]")。这样您就不允许使用某些字符,例如“;”或“\”从而禁用 SQL 注入攻击。阅读 SQL 注入...通过谷歌搜索。
  • 不客气。祝您未来的编码企业好运。
猜你喜欢
  • 2011-11-25
  • 2012-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-01
  • 2015-02-16
  • 2020-04-17
  • 2014-11-11
相关资源
最近更新 更多