2017-01-27 2 views
1

Je suis confronté à un problème de performances avec Hibernate sessionFactory. Il est une botte de Spring - Hibernate application avec un SessionFactory configuré comme celui-ciProblème de performance de Spring & Hibernate SessionFactory

@Bean 
public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf){ 
    return hemf.getSessionFactory(); 
} 

J'ai aussi essayé toutes les différentes manières décrites dans cette question Spring Boot - Handle to Hibernate SessionFactory

Mon OAC ressemble à ceci

@Autowired 
private SessionFactory sessionFactory; 


@Transactional 
public List<Type> findAll() { 
    return sessionFactory.getCurrentSession().createQuery("from Type").list(); 
} 

Lorsque le nombre de requêtes db simultanées est supérieur au nombre maximal de paramètres configuré (10 dans cet exemple), l'application ne répond plus.

@RequestMapping(value = "/stress-sessionfactory") 
public void stressTest(@RequestParam int threadsCount) { 
    List<Thread> threads = new ArrayList<>(); 
    for (int i = 0; i < threadsCount; i++) { 
     final int k = i; 
     Runnable runnable 
       =() -> { 

      List<Type> all = typeDAOHibernate.findAll(); 
      LOG.info("{}:sessionfactory:{} ", k, all.size()); 
     }; 
     Thread t = new Thread(runnable); 
     threads.add(t); 
    } 
    threads.stream().forEach(t -> t.start()); 
} 

Vous pouvez trouver un exemple autonome dans github. L'exemple est configuré avec maximumPoolSize=10. Donc si vous venez de frapper http://localhost:8080/stress-sessionfactory?threadsCount=11 vous obtiendrez l'erreur dont je parle. D'autre part, un référentiel Spring Data peut facilement gérer des milliers de demandes simultanées! (Par exemple http://localhost:8080/stress-jpa?threadsCount=2000)

J'ai essayé le même scénario avec différentes sources de données (Hikari, Tomcat), bases de données différentes (oracle, h2) et différentes versions Mise en veille prolongée (5,011-finale, v4.3.11-finale) et je reçois toujours la même erreur.

Stacktrace

Exception in thread "Thread-51" Exception in thread "Thread-47" org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:431) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:447) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:277) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) at com.example.dao.TypeDAOHibernate$$EnhancerBySpringCGLIB$$e6373e2e.findAll(<generated>) at com.example.controller.StressController.lambda$stressTest$0(StressController.java:36) at java.lang.Thread.run(Thread.java:745) Caused by: javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1700) at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:48) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:189) at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:380) ... 9 more Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:48) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:90) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:112) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:230) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:237) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214) at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52) at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1512) at org.hibernate.jpa.internal.TransactionImpl.begin(TransactionImpl.java:45) ... 11 more Caused by: java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30001ms. at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:591) at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:194) at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:146) at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:386) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:87) ... 18 more []

Répondre

0

Je remarque que vous injectez sessionFactory mais pas l'utilisation des fonctions de transaction-cadre de printemps. Si vous voulez utiliser comme ceci vous devez fermer la session que vous obtenez de sessionFactory dans la couche dao.

+1

Salut, avez-vous vérifié votre solution proposée? Ça a marché? Cela ne semble pas être la réponse à la question de l'affiche! – pleft

+0

Oui La méthode findAll est déjà marquée comme transactionnelle. Autre que cela j'ai essayé de fermer la session manuellement dans la méthode mais le problème se produit toujours. Ce n'est pas le cas – ltsallas