2015-10-01 1 views
15

J'essaie donc d'utiliser Spring pour gérer les transactions d'hibernation pour la première fois, et quelque chose ne va pas. Je ne suis pas sûr de quoi. J'ai regardé un tas de réponses similaires sur ce site et rien de ce que j'ai vu ne semble avoir raison. Donc, je vais copier et coller un tas de mon code avec quelques explications et demander de l'aide ici.Hibernate & Spring: Exception lors de la création d'une transaction

Voici une trace de pile de l'exception que je reçois. Essentiellement, il semble qu'il essaie de trouver org.hibernate.engine.transaction.spi.transactioncontext, et ne peut pas.

pile d'exception trace

EXCEPTION: Could not open Hibernate Session for transaction; nested exception is java.lang.NoClassDefFoundError: org/hibernate/engine/transaction/spi/TransactionContext 
org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:544) 
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) 
org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427) 
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276) 
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 
com.sun.proxy.$Proxy42.getSavedPortfolios(Unknown Source) 
io.craigmiller160.stockmarket.controller.StockMarketController.showOpenPortfolioDialog(StockMarketController.java:994) 
io.craigmiller160.stockmarket.controller.StockMarketController.parseEvent(StockMarketController.java:431) 
io.craigmiller160.stockmarket.controller.StockMarketController.processEvent(StockMarketController.java:336) 
io.craigmiller160.mvp.concurrent.AbstractConcurrentListenerController$1.run(AbstractConcurrentListenerController.java:209) 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
java.lang.Thread.run(Thread.java:745) 

Maintenant, je l'ai cherché sur ce site, et la grande chose que je voyais était que cela veut dire que j'ai une dépendance mal dans ma pom.xml. La chose est, j'ai la version la plus à jour de la dépendance hibernate-core dans mon pom. D'après ce que j'ai lu, c'est ce dont j'ai besoin pour cette classe.

dépendances pom.xml

<dependencies> 
<!-- JUnit Testing --> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>4.12</version> 
     <scope>test</scope> 
    </dependency> 
<!-- MVP Framework --> 
    <dependency> 
     <groupId>io.craigmiller160.mvp</groupId> 
     <artifactId>mvp-framework</artifactId> 
     <version>2.1.1</version> 
    </dependency> 
<!-- MigLayout --> 
    <dependency> 
     <groupId>com.miglayout</groupId> 
     <artifactId>miglayout-swing</artifactId> 
     <version>5.0</version> 
    </dependency> 
<!-- JFreeChart --> 
    <dependency> 
     <groupId>org.jfree</groupId> 
     <artifactId>jfreechart</artifactId> 
     <version>1.0.19</version> 
    </dependency> 
<!-- Java Concurrency In Practice Annotations --> 
    <dependency> 
     <groupId>net.jcip</groupId> 
     <artifactId>jcip-annotations</artifactId> 
     <version>1.0</version> 
    </dependency> 
<!-- Joda Time --> 
    <dependency> 
     <groupId>joda-time</groupId> 
     <artifactId>joda-time</artifactId> 
     <version>2.8.2</version> 
    </dependency> 
<!-- MySQL ConnectorJ --> 
    <dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
     <version>5.1.36</version> 
    </dependency> 
<!-- Spring Framework Core --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-core</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
<!-- Spring Framework Beans --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-beans</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
<!-- Spring Framework Context --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
<!-- Hibernate Core --> 
    <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-core</artifactId> 
     <version>5.0.1.Final</version> 
    </dependency> 
<!-- XML Framework --> 
    <dependency> 
     <groupId>dom4j</groupId> 
     <artifactId>dom4j</artifactId> 
     <version>1.6.1</version> 
    </dependency> 
<!-- Code Generation library --> 
    <dependency> 
     <groupId>cglib</groupId> 
     <artifactId>cglib</artifactId> 
     <version>3.1</version> 
    </dependency> 
<!-- Apache Commons Logging --> 
    <dependency> 
     <groupId>commons-logging</groupId> 
     <artifactId>commons-logging</artifactId> 
     <version>1.2</version> 
    </dependency> 
<!-- LOG4J API --> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-api</artifactId> 
     <version>${log4j.version}</version> 
    </dependency> 
<!-- LOG4J Core --> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-core</artifactId> 
     <version>${log4j.version}</version> 
    </dependency> 
<!-- SLF4J/LOG4J Binding --> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-slf4j-impl</artifactId> 
     <version>${log4j.version}</version> 
    </dependency> 
<!-- LOG4J/Commons Logging Binding --> 
    <dependency> 
     <groupId>org.apache.logging.log4j</groupId> 
     <artifactId>log4j-jcl</artifactId> 
     <version>${log4j.version}</version> 
    </dependency> 
<!-- SLF4J API --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-api</artifactId> 
     <version>1.7.12</version> 
    </dependency> 
<!-- Spring ORM --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-orm</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
<!-- AspectJ Runtime --> 
    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjrt</artifactId> 
     <version>${aspectj.version}</version> 
    </dependency> 
<!-- AspectJ Weaver --> 
    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjweaver</artifactId> 
     <version>${aspectj.version}</version> 
    </dependency> 
<!-- Apache Database Connection Pooling --> 
    <dependency> 
     <groupId>org.apache.commons</groupId> 
     <artifactId>commons-dbcp2</artifactId> 
     <version>2.1.1</version> 
    </dependency> 
</dependencies> 

En outre, j'ajoute la méthode réelle dans mon DAO que je vous appelle. Cette méthode est ce qui tente de s'exécuter lorsque l'exception est levée.

méthode DAO:

@Transactional 
@Override 
@SuppressWarnings("unchecked") //hibernate list() method doesn't support generics 
public List<String> getSavedPortfolios() throws HibernateException { 
    List<String> portfolioNames = new ArrayList<>(); 

    List<SQLPortfolioModel> portfolioList = sessionFactory.getCurrentSession() 
           .createCriteria(PortfolioModel.class) 
           .list(); 

    for(SQLPortfolioModel portfolio : portfolioList){ 
     int id = portfolio.getUserID(); 
     String name = portfolio.getPortfolioName(); 
     BigDecimal netWorth = portfolio.getNetWorth(); 
     Calendar timestamp = portfolio.getTimestamp(); 

     String fileName = String.format("%1$d-%2$s-%3$s-" 
       +"%4$s", id, name, moneyFormat.format(netWorth), 
       timestampFormat.format(timestamp.getTime())); 
     portfolioNames.add(fileName); 
    } 

    return portfolioNames; 
} 

Enfin, voici mon ressort contexte data.xml. Il contient toute la configuration de mes grains de données pour le printemps, plus la substance de la transaction:

printemps-contexte data.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx.xsd"> 

<!-- Sets annotation-driven transactions --> 
<tx:annotation-driven transaction-manager="transactionManager"/> 

<!-- DataSource object for providing database connections --> 
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/> 
    <property name="url" value="jdbc:mysql://localhost/stockmarket"/> 
    <property name="username" value="stockmarket"/> 
    <property name="password" value="stockmarket"/> 
</bean> 

<!-- SessionFactory object for creating sessions for database access --> 
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <!-- <property name="configLocation" value="classpath:hibernate.cfg.xml"/>--> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <prop key="connection.pool_size">1</prop> 
      <prop key="show_sql">false</prop> 
      <!-- Might need this one below for transactions, not sure yet --> 
      <prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop> 
     </props> 
    </property> 
    <property name="annotatedClasses"> 
     <list> 
      <value>io.craigmiller160.stockmarket.stock.AbstractStock</value> 
      <value>io.craigmiller160.stockmarket.stock.OwnedStock</value> 
      <value>io.craigmiller160.stockmarket.stock.DefaultStock</value> 
      <value>io.craigmiller160.stockmarket.stock.DefaultOwnedStock</value> 
      <value>io.craigmiller160.stockmarket.model.PortfolioModel</value> 
      <value>io.craigmiller160.stockmarket.model.SQLPortfolioModel</value> 
     </list> 
    </property> 
</bean> 

<!-- Hibernate Transaction Manager --> 
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

<!-- HibernateDAO class for performing database operations --> 
<bean id="hibernateDao" class="io.craigmiller160.stockmarket.controller.HibernatePortfolioDAO" 
    destroy-method="closeFactory"> 
    <constructor-arg ref="sessionFactory"/> 
</bean> 

</beans> 

donc je n'ai aucune idée pourquoi cela se passe. J'ai vérifié deux fois ce que j'ai fait et ce que je vois en ligne, et je ne peux pas voir l'erreur. C'est la première fois que j'essaie d'utiliser la gestion des transactions Spring. Toute aide serait grandement appréciée.

PS. J'utilise Spring 4 & Hibernate 5 ensemble, si cela fait une différence.

+0

Vous utilisez hibernate4 selon Spring, mais vous avez des dépendances hibernate5. Cela ne va pas fonctionner soit basculer vers la bonne 'LocalSessionFactoryBean' ou passer à hibernate4 –

+0

Quelle version de Spring 4 avez-vous exactement? Seulement Spring 4.2 et versions ultérieures supportent Hibernate 5. Si vous avez Spring 4.1, vous pouvez utiliser Hibernate 4.3 comme version la plus haute. – dunni

Répondre

0

Vous ne savez pas si c'est le problème, mais étant donné que vous pensez qu'il s'agit d'un problème lié au fichier pom.xml, essayez d'ajouter la dépendance du gestionnaire d'entités d'Hibernate. J'ai comparé votre pom.xml au mien et, en ce qui concerne les dépendances d'hibernate, c'est celui qui manque.

+0

pouvez-vous spécifier exactement quelle dépendance me manque? – user2223059

+0

ici http://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager/5.0.0.Final –

5

La classe qu'il recherche se réfère à une classe qui existe seulement dans Hibernate 4.x http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/engine/transaction/spi/package-summary.html

Mais pas plus 5.x http://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/engine/transaction/spi/package-summary.html

Je pense que vous pourriez être mixez Hibernate 4 et 5 dépendances. Je ne pense pas que vous pouvez simplement changer la version d'hibernation sans passer en revue toutes ses dépendances.

+0

Alors devrais-je simplement revenir à Hibernate 4 alors? Et tous mes problèmes seront résolus? – user2223059

+0

Eureka! Cela a fonctionné, merci beaucoup. Donc, seul le bogue restant est que maintenant, une partie de la journalisation d'hibernate s'imprime dans la console plutôt que d'être routée vers mon fichier Appender dans log4j2. Cela ne se produisait pas lorsque j'utilisais la version 5. Mon POM a les dépendances que j'ai pour m'assurer que toute la journalisation de slf4j est correctement routée, une idée de ce qui se passe? (Petit détail, je sais, mais je suis très orienté détail) – user2223059

+0

"une partie de la journalisation d'hibernate" est quoi exactement? Je préférerais probablement ouvrir une nouvelle question sur stackoverflow pour cela, afin qu'elle reçoive la bonne attention et que vous puissiez poster quelques exemples de configs. –

45

Dans votre POM vous êtes en fonction de mise en veille prolongée 5, mais dans votre gestionnaire de transactions, vous utilisez Hibernate 4.

Changer votre gestionnaire de transacation pour correspondre à votre pom (à savoirde hibernate4 à hibernate5):

<bean id="transactionManager" 
     class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

Si cela provoque une erreur de classe non trouvée, mettre à jour votre cadre de printemps à 4.2.2

+3

Merci! Travaillez comme un charme pour moi. – Deoxyseia

+0

On dirait que c'est la bonne réponse mais pouvez-vous la traduire en mode @annotation, votre réponse sera plus parfaite et plus utile ... et merci. –

+0

m'a sauvé un jour :) –

-1

Je recevais le même problème et mon problème sont résolus par la mise à jour

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
<property name="sessionFactory" ref="sessionFactory"/> 

+1

N'avez-vous pas vu que cette approche exacte a déjà été émise par quelqu'un? Il vaut mieux que vous commentiez que de poster ceci comme une réponse. – larrytech

2

vous utilisez hibernate-5, mais vous demandez au printemps d'utiliser hibernate-4 sessionFactory

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 

et gestionnaire de transactions

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">