为什么数据库连接一直关闭

Why is DataBase Connecton keeps closing

我真的被这个问题困住了,所以我很高兴有人能帮助我!

当我在一分钟后登录时,当我尝试再次登录时系统注销,我收到此错误:com.mysql.jdbc.exceptions。jdbc4.MySQLNonTransientConnectionException:连接关闭后不允许进行任何操作。

如何防止此连接关闭。最好的连接池是什么

注意:我仍然是一个学习者,正在做我的第一个 CRUD! 数据库实用程序:

  private static Connection connet;
        public static Connection getConnection() {
            if( connet != null )
                return connet;

            InputStream inputStream = DButil.class.getClassLoader().getResourceAsStream( "/db.properties" );
            Properties properties = new Properties();
            try {
                properties.load( inputStream );
                String url = properties.getProperty("url");
                String driver = properties.getProperty("driver");
                String userName = properties.getProperty("user");
                String password = properties.getProperty("password");

                Class.forName(driver);
                connet = DriverManager.getConnection(url,userName,password);

            } catch (IOException | ClassNotFoundException | SQLException e) {

                e.printStackTrace();
            }

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

    }

      // rollback data
      public static void rollback() {
        if (connet != null) {
            try {
                connet.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
    }

    // close Connection
    public static void closeConnection( Connection toBeClosed ) {
        if( toBeClosed == null )
            return;
        try {
            toBeClosed.close();
        } catch (SQLException e) {
            e.printStackTrace();

        }
    }

数据库属性:

url = jdbc:mysql://localhost:3306/dbname?autoReconnect=true
driver = com.mysql.jdbc.Driver
user = usernanem
password = password

道实现:

private Connection connet;

    public UsersDaoImplementation()
    {
        connet=DButil.getConnection();
    }

    @Override
    public void addUser(Users user) {

        try {
            String query = "INSERT INTO Users (First_Name, Last_Name, Address, Phone_Number, UserName, Password, idRole, Date_of_Birth) VALUES (?,?,?,?,?,?,?,?)";

            PreparedStatement preparedStatement = connet.prepareStatement( query );
            preparedStatement.setString(1, user.getFirst_Name());
            preparedStatement.setString(2, user.getLast_Name());
            preparedStatement.setString(3,user.getAddress());
            preparedStatement.setInt(4, user.getPhone_Number());
            preparedStatement.setString(5, user.getUserName());
            preparedStatement.setString(6, user.getPassword());
            preparedStatement.setInt(7, user.getIdRole());
            //preparedStatement.setDate(8, (Date) user.getDate_of_Birth());
            //preparedStatement.setDate(8, (java.sql.Date) user.getDate_of_Birth());
            preparedStatement.setDate(8, new java.sql.Date (user.getDate_of_Birth().getTime()));

            preparedStatement.executeUpdate();
            preparedStatement.close();

        } catch (SQLException e) {

            e.printStackTrace();
        }

    }

    @Override
    public void deleteUser(int idUsers) {
        try {
            String query ="DELETE FROM Users WHERE idUsers = ?";
            PreparedStatement preparedStatement = connet.prepareStatement( query );
            preparedStatement.setInt(1, idUsers);
            preparedStatement.executeUpdate();
            preparedStatement.close();
        } catch (SQLException e) {

            e.printStackTrace();
        }


    }

    @Override
    public void updateUser(Users user) {
        try {
             String query = "UPDATE Users SET First_Name=?, Last_Name=?, Address=?, Phone_Number=?, UserName=?, Password=?, idRole=?, Date_of_Birth=?";

            PreparedStatement preparedStatement = connet.prepareStatement( query );
            preparedStatement.setString(1, user.getFirst_Name());
            preparedStatement.setString(2, user.getLast_Name());
            preparedStatement.setString(3,user.getAddress());
            preparedStatement.setInt(4, user.getPhone_Number());
            preparedStatement.setString(5, user.getUserName());
            preparedStatement.setString(6, user.getPassword());
            preparedStatement.setInt(7, user.getIdRole());
            preparedStatement.setDate(8, new java.sql.Date (user.getDate_of_Birth().getTime()));
            preparedStatement.executeUpdate();
            preparedStatement.close();
        } catch (SQLException e) {

            e.printStackTrace();
        }

    }

    @Override
    public List<Users> getAllUsers() {
        List<Users> users = new ArrayList<Users>();     
        try {
            Statement statement = connet.createStatement();
            ResultSet resultSet = statement.executeQuery( "SELECT * FROM Users" );
            while (resultSet.next())
            {
                Users user = new Users();
                user.setIdUsers(resultSet.getInt("idUsers"));
                user.setFirst_Name(resultSet.getString("First_Name"));
                user.setLast_Name(resultSet.getString("Last_Name"));
                user.setAddress(resultSet.getString("Address"));
                user.setPhone_Number(resultSet.getInt("Phone_Number"));
                user.setUserName(resultSet.getString("UserName"));
                user.setPassword(resultSet.getString("Password"));
                user.setIdRole(resultSet.getInt("idRole"));
                user.setDate_of_Birth(resultSet.getDate("Date_of_Birth"));
                users.add(user);
            }
            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return users;
    }

    @Override
    public Users getUserbyId(int idUsers) {
Users user = new Users();

        try {
            String query = "SELECT * FROM Users WHERE idUsers=?";
            PreparedStatement preparedStatement = connet.prepareStatement( query );

            preparedStatement.setInt(1, idUsers);
            ResultSet resultSet = preparedStatement.executeQuery();

            while( resultSet.next() ) {
            user.setIdUsers(resultSet.getInt("idUsers"));
            user.setFirst_Name(resultSet.getString("First_Name"));
            user.setLast_Name(resultSet.getString("Last_Name"));
            user.setAddress(resultSet.getString("Address"));
            user.setPhone_Number(resultSet.getInt("Phone_Number"));
            user.setUserName(resultSet.getString("UserName"));
            user.setPassword(resultSet.getString("Password"));
            user.setIdRole(resultSet.getInt("idRole"));
            user.setDate_of_Birth(resultSet.getDate("Date_of_Birth"));

        } 
        resultSet.close();
        preparedStatement.close();

    }
        catch (SQLException e) {

            e.printStackTrace();
        }
        return user;
    }



    @Override
    public boolean validate(String UserName, String Password) {
        boolean status = false;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            String query =  "SELECT * FROM Users WHERE UserName=? and Password=?";
         preparedStatement = connet.prepareStatement( query );

            preparedStatement.setString(1, UserName);
            preparedStatement.setString(2, Password);
            resultSet = preparedStatement.executeQuery();

            status=resultSet.next();

        } catch (SQLException e) {

            e.printStackTrace();
        }finally {
            if (connet != null) {
                try {
                    connet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return status;
    }

错误:

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:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:377)
    at com.mysql.jdbc.Util.getInstance(Util.java:360)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:924)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:870)
    at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1232)
    at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1225)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4104)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4073)
    at org.jupiterM.dao.UsersDaoImplementation.validate(UsersDaoImplementation.java:162)
    at org.jupiterM.controller.LoginJ.doPost(LoginJ.java:63)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

您有一个 finally 块,内容如下:

} finally {
    if (connet != null) {
        try {
            connet.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    ...
}

由于connet是字段,关闭的连接会保留在实例上;不过,它不会设置为 null

这样做的结果是关闭的连接将返回给您,因为您所检查的只是它不是 null

您可以通过更改获取新连接的代码来解决此问题:

if( connet != null && !connet.isClosed() )
    return connet;

您应该做的另一件事是在关闭时将 connet 设置为 null

您有一个静态属性,即您的连接。该对象正在返回给您的 dao 中的方法。当您关闭他的连接时,您也关闭了静态连接。 (因为它们共享相同的引用)。您应该在每个方法上创建连接对象,或者寻找一个框架来控制您的连接。连接池真的很难以纯粹的jdbc方式实现。

No operations allowed after connection closed. How can I prevent this connection closed Exception ?

选项 (1): 最后通过空检查关闭连接

您可以通过在 finally 块中添加 null 检查和关闭连接来防止这种情况,如下所示:

Connection conn = null;
try {
  //your code
} catch(SQLException exe) {
 //Log exceptions
} finally {
   try {
       conn.close();
    } catch (SQLException e) {
       e.printStackTrace();
    }
}

我在你的代码中注意到,有时你会关闭 try 中的连接,这是不推荐的,因为如果 try 块在中间抛出一个 SQLExceptionconn.close() 将不会被执行,这是一个非常大的问题。因此,请确保您始终仅在 finally 块中关闭连接,否则会造成资源泄漏(很快您将 运行 失去连接)。

选项(2): 你可以尝试使用资源(推荐,因为你不需要担心关闭连接)

try(Connection conn = DButil.getConnection()) {
  //your code
} catch(SQLException exe) {
 //Log exceptions
}

这里,在选项(2)中,你可以注意到这里没有finally块,conn object会自动变成closed,你可以看here 有关 try with resources.

的更多详细信息

How can I handle connection pool for my code ?

手动处理连接(就像您所做的那样)不是最佳实践(因为它们在时间方面成本很高),因此您可以尝试使用 Apache DBCP 实现连接池您可以参考 here 了解更多信息。

修复此错误是一个有争议的问题 - 因为您的方法的整个想法是错误的 - 在不同线程之间共享单个连接(并且每个请求可能来自不同的线程)是完全禁止的。即使您使用其他建议之一并摆脱了这个错误,您也会遇到更多错误——更糟糕的错误。一旦你添加任何类型的交易,你将永远无法让它工作。

如果您使用 Java EE 或 Java EE Web 配置文件兼容的服务器,它有一个内置的连接池,以及配置它的工具,为每个请求创建一个新连接,安全地 return 连接到池并执行事务(甚至是两阶段提交)。如何配置它的具体细节取决于服务器,通常有专有配置文件或一些管理图形用户界面。