Как избежать ошибок тайм-аута подключения MySQL с помощью EclipseLink?

MySQL закрывает соединение по истечении определенного времени, если ничего не происходит (8 часов к по умолчанию). На время может влиять переменная wait_timeout в конфигурации.

У меня есть приложение Eclipse RCP, в котором я использую EclipseLink в качестве среды постоянства, и я получаю сообщение об ошибке, когда клиент превышает время ожидания:

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: 
       No operations allowed after connection closed.
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   ...
   at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
   at com.mysql.jdbc.Util.getInstance(Util.java:386)
       ...
   com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException
   ...
       org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor...

Я пытался установить autoReconnect/autoReconnectForPools=true, но это не помогает.

Спасибо

ИЗМЕНИТЬ

В моем файле persistence.xml у меня установлены следующие свойства:

    <property 
      name="eclipselink.jdbc.read-connections.max"
      value="10" />
    <property 
      name="eclipselink.jdbc.cache-statements" 
      value="true" />
    <property 
      name="eclipselink.jdbc.read-connections.shared"
      value="true" />

Остальные настройки выполняются в коде:

    Map<Object, Object> map = ...
    map.put(PersistenceUnitProperties.JDBC_URL,...);
    map.put(PersistenceUnitProperties.JDBC_USER,...);
    map.put(PersistenceUnitProperties.JDBC_PASSWORD, ...);
    map.put(PersistenceUnitProperties.JDBC_DRIVER,  ...);
    map.put(PersistenceUnitProperties.CLASSLOADER, this.getClass()
            .getClassLoader());
    map.put(PersistenceUnitProperties.TARGET_DATABASE, "MySQL");
    entityManagerFactory = new PersistenceProvider()
            .createEntityManagerFactory("...", map);

person Michael    schedule 02.12.2011    source источник


Ответы (2)


EclipseLink должен автоматически переподключать мертвые соединения. EclipseLink перехватит ошибку, проверит соединение и, если оно не работает, переподключится и, возможно, повторит запрос (если вне транзакции).

Но это зависит от того, какой пул соединений вы используете, каков ваш файл persistence.xml.

person James    schedule 05.12.2011
comment
Большое спасибо за ответ. Я добавил свою конфигурацию к вопросу. Я не нашел решения, как настроить это в файле persistence.xml. - person Michael; 06.12.2011
comment
Какую версию EclipseLink вы используете? Можете ли вы включить полный стек исключений и объяснить, когда вы его получите. Если вы обработаете ошибку и повторите попытку, вы снова получите ошибку? - person James; 07.12.2011
comment
Также удалите настройки eclipselink.jdbc.read-connections.max и eclipselink.jdbc.read-connections.shared, это не рекомендуется. Используйте eclipselink.connection-pool.default.max, чтобы установить максимальное значение (по умолчанию 32), если вы не используете более старую версию. - person James; 07.12.2011
comment
Я использовал EclipseLink 2.2.0. и обновлен до 2.3.1. Я также изменил настройки параметров, как вы сказали. После этого я больше не могу воспроизвести ошибку. Большое спасибо, Джеймс, за помощь. - person Michael; 07.12.2011

Самый простой способ сделать это — создать поток, который отправляет какое-то сообщение проверки активности или простой запрос каждый час или около того. Здесь мы бы оставили флаг, чтобы поток мог останавливаться при выходе из программы, изменении базы данных и т. д. Если ему нужно быстрее реагировать на такой тип завершения работы, вы можете изменить счетчик в цикле for и время ожидания.

boolean parentKilledMe = false;
while (!parentKilledMe){
    //put query here
    for (int x = 0; x < 360 && !parentKilledMe;x++){
        try{
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            //your error handling here
        }
    }
}
person Thomas    schedule 02.12.2011