Почему соединение с базой данных продолжает закрываться

Я действительно застрял с этой проблемой, поэтому я был бы рад, если бы кто-то мог мне помочь!

когда я вхожу в систему через минуту, система выходит из системы, когда я пытаюсь снова войти в систему, я получаю эту ошибку: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: после закрытия соединения операции не разрешены.

Как я могу предотвратить это соединение закрыто. и какой будет лучший пул соединений для этого

NB: я все еще учусь, делаю свой первый 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)

person ivan    schedule 06.11.2016    source источник
comment
ivan: Вы можете посмотреть мой ответ с более подробной информацией об этой ошибке.   -  person developer    schedule 07.11.2016
comment
Вы действительно не должны использовать статическое поле с соединением в веб-приложении...   -  person Mark Rotteveel    schedule 07.11.2016


Ответы (4)


У вас есть блок 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, когда он был закрыт.

person Sergey Kalinichenko    schedule 06.11.2016
comment
Это может решить насущную проблему, но весь код с одним общим подключением — это несчастный случай, ожидающий своего появления в веб-приложении. - person Mark Rotteveel; 07.11.2016

Никакие операции не разрешены после закрытия соединения. Как я могу предотвратить закрытие этого соединения Exception ?

Вариант (1): закрыть соединение с нулевой проверкой

Вы можете предотвратить это, добавив проверку null и закрыв соединения в блоке finally, как показано ниже:

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

Я заметил в вашем коде, что иногда вы закрываете соединения внутри try, что не рекомендуется, потому что, если блок try выбрасывает SQLException в середине, conn.close() НЕ будет выполняться, что является очень большой проблемой. Поэтому убедитесь, что вы ВСЕГДА закрываете соединения ТОЛЬКО в блоке finally, иначе это приведет к УТЕЧКЕ РЕСУРСОВ (очень скоро у вас закончатся соединения).

Вариант (2). Вы можете использовать попытку с ресурсами (рекомендуется, так как вам не нужно беспокоиться о закрытии соединения)

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

Здесь, в Варианте (2), вы можете заметить, что здесь НЕТ блока finally, и conn object автоматически будет closed, вы можете посмотреть здесь подробнее о try with resources.

Как я могу обрабатывать пул соединений для моего кода?

Обработка подключений вручную (как вы это делали) НЕ является лучшей практикой (поскольку это дорого с точки зрения времени), поэтому вы можете попробовать реализовать пул подключений с помощью Apache DBCP, и вы можете обратиться здесь, чтобы узнать больше об этом.

person developer    schedule 06.11.2016

У вас есть один статический атрибут, который является вашим соединением. Объект возвращается к методам в вашем дао. Когда вы закрываете его соединение, вы также закрываете статическое. (Потому что они имеют одну и ту же ссылку). Вы должны создать объект подключения для каждого метода или найти фреймворк для управления вашими подключениями. Пул соединений действительно сложно получить в чистом виде jdbc.

person Bruno    schedule 06.11.2016
comment
Понижение не является личным, на самом деле мне очень жаль - но действительно странно говорить о работе с java ee, верно? [...] затем используйте spring, поскольку Java EE имеет все встроенные средства для подключений/транзакций и т. д. - без необходимости втягивать/настраивать целую дополнительную структуру. Я не говорю, что Spring плохой - просто ваше предложение не имеет смысла. - person fdreger; 07.11.2016
comment
Rlx, просто объясните отрицательный голос, если хотите ... Что не так с моим ответом - person Bruno; 07.11.2016
comment
Ваш ответ имеет смысл, за исключением последнего совета, который просто странен (для меня это звучит так: о, вы уже используете Spring? Тогда добавьте Google Guice для обработки внедрения зависимостей) и может быть воспринято буквально, если ответ был одобрен . - person fdreger; 07.11.2016
comment
Что я пытаюсь посоветовать, так это то, что существует множество фреймворков, которые помогают контролировать соединение с базой данных, особенно в распределенных веб-системах... - person Bruno; 07.11.2016
comment
Как вы думаете, я могу сделать это лучше ответа? Не могли бы вы отредактировать мой ответ? мне бы очень понравилось - person Bruno; 07.11.2016
comment
Я понимаю - и мне нравится Весна. Но ОП говорит, что он уже использует фреймворк - Java EE 7 (если это правда, это другой вопрос). JEE7 имеет все возможности Spring в этой области (и с более простой конфигурацией). Нет смысла предлагать заглянуть в один фреймворк, когда в вопросе уже упоминается другой. Просто удалите последнее предложение. - person fdreger; 07.11.2016
comment
Отредактировано! Сейчас лучше? - person Bruno; 07.11.2016
comment
да :) Извините за анальное сохранение :) - person fdreger; 07.11.2016
comment
Давайте продолжим обсуждение в чате. - person Bruno; 07.11.2016

Исправление этой ошибки является спорным вопросом, поскольку вся идея вашего подхода неверна - совместное использование одного соединения между разными потоками (и каждый запрос может поступать в другом потоке) просто запрещено. Даже если вы воспользуетесь одним из других предложений и избавитесь от этой единственной ошибки, вы получите больше ошибок, причем более серьезных. И вы никогда не сможете заставить его работать после добавления транзакций любого типа.

Если вы используете сервер, совместимый с Java EE или веб-профилем Java EE, он имеет встроенный пул соединений, а также средства для его настройки, создания нового соединения для каждого запроса, безопасного возврата соединения в пул и выполнения транзакции (даже двухфазный коммит). Точные сведения о том, как его настроить, зависят от сервера, обычно это проприетарный файл конфигурации или некоторый графический интерфейс администратора.

person fdreger    schedule 06.11.2016