2 votes

La connexion est fermée lors de l'utilisation d'Hibernate Search avec une application Spring

Depuis que j'ai ajouté Hibernate Search à mon application, il semble que je perde la connexion du pool d'Hikari après un certain temps (il semble que ce soit plus de 8 heures).

Cela fait une semaine que je suis confronté à cette erreur et je ne sais pas vraiment pourquoi elle se produit :

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement

Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement

Caused by: java.sql.SQLException: Connection is closed

J'ai essayé : de définir les propriétés de certains hikari comme :

 spring.datasource.type=com.zaxxer.hikari.HikariDataSource
 spring.datasource.hikari.minimumIdle=20
 spring.datasource.hikari.maximumPoolSize=100
 spring.datasource.hikari.idleTimeout=300000
 spring.datasource.hikari.poolName=SpringBootJPAHikariCP
 spring.datasource.hikari.maxLifetime=200000
 spring.datasource.hikari.connectionTimeout=20000
 spring.datasource.hikari.registerMbeans=true

pour configurer mon bean afin qu'il utilise une testQuery comme ci-dessous :

    public DataSource siteDataSource() {

    HikariConfig config = new HikariConfig();
    HikariDataSource dataSource;

    config.setJdbcUrl(env.getProperty("spring.mysql.datasource.url"));
    config.setUsername(env.getProperty("spring.mysql.datasource.username"));
    config.setPassword(env.getProperty("spring.mysql.datasource.password"));
    config.setDriverClassName(env.getProperty("spring.mysql.datasource.driver-class-name"));
    config.setMaximumPoolSize(15);
    config.setConnectionTestQuery("SELECT 1");

    // performance senstive settings
    config.setMinimumIdle(0);
    config.setConnectionTimeout(30000);
    config.setIdleTimeout(35000);
    config.setMaxLifetime(45000);
    dataSource = new HikariDataSource(config);

    return dataSource;
}

(les éléments de cette configuration ont également été supprimés et l'erreur est toujours la même)

et à utiliser :

autoReconnect=true

J'obtenais également l'erreur ci-dessous, qui semble avoir disparu avec l'implémentation actuelle (mais pour être honnête, je n'ai aucune idée de pourquoi - oui, je suis assez perdu ici) :

Caused by: com.mysql.cj.exceptions.CJCommunicationsException: The last packet successfully received from the server was 50,090,585 milliseconds ago.  The last packet sent successfully to the server was 50,090,585 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

Je ne sais même pas comment reproduire cette erreur. Je dois attendre une journée entière pour le tester à nouveau à chaque nouveau test.

Il semble qu'il y ait quelque chose avec Tomcat + Hibernate + Hikari, mais pour être honnête, je n'ai pas d'autre idée.

Avez-vous une idée pour résoudre ce problème, ou même pour reproduire cette erreur sur une courte période de temps ?

Merci.

0voto

Ahmed Ramadan Points 1

Cette erreur a été résolue en recréant l'objet entityManager.

this.entityManager = entityManagerFactory.createEntityManager() ;

Il suffit donc d'attraper l'exception et de recréer l'objet entityManager, puis d'effectuer une nouvelle recherche.

optionnellement lire (recommandation d'index manuel) Lorsque j'enregistre (crée/met à jour) un objet dans la base de données par Jpa, j'ai l'impression d'être en train de faire une erreur.

repository.save(obj)

a constaté que l'objet n'est pas indexé dans hibernate-search( Lucien/Elastic Search/.. ), je dois donc indexer l'objet manuellement après l'avoir enregistré dans la base de données ( mais je n'ai pas besoin de supprimer manuellement l'objet indexé lorsqu'il est supprimé de la base de données. ).

repository.save(objFromDB);
manualIndexToHibernateSearch(objFromDB);
...
public void manualIndexToHibernateSearch(MyObject objFromDB) {
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
    fullTextEntityManager.getTransaction().begin();
    //find object by id in hibernate-search 
    MyObject objFromHibernateSearch = fullTextEntityManager.find(MyObject.class, objFromDB.getId());
    //you have to replace 'text' field with your fields that have @Field annotation
    objFromHibernateSearch.setText(objFromDB.getText());
    //index
    fullTextEntityManager.index(objFromHibernateSearch);
    //commit
    fullTextEntityManager.getTransaction().commit();
}

0voto

Zon Points 518

Les étapes qui nous ont aidés à résoudre le même problème :

  • Mettez à jour votre version de SpringBoot.
  • Mettez à jour la version de la bibliothèque de votre connecteur de base de données.
  • Supprimez les autres bibliothèques de mise en commun des connexions à la base de données, car c'est généralement Hikari de SpringBoot qui doit être utilisé par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X