Je suis nouveau sur Spring et JPA, j'ai perdu 5 jours et aucun résultat avec la recherche sur Internet. Je souhaite enregistrer l'objet dans SQL SERVER, la connexion est correcte mais lorsque j'écris .flush (), j'obtiens l'exception
l'exception imbriquée est javax.persistence.TransactionRequiredException: aucune transaction n'est en cours
C'est mon jpaContext.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:context="http://www.springframework.org/schema/context"
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/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.misha.service"/>
<context:component-scan base-package="com.misha.repository"/>
<context:component-scan base-package="com.misha.model"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="myEntityManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.misha.model"/>
<property name="persistenceUnitName" value="test" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
<property name="url"
value="jdbc:jtds:sqlserver://127.0.0.1;instance=SQLEXPRESS;DatabaseName=misha" />
<property name="username" value="sa" />
<property name="password" value="root" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEntityManager" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
Voici mon fichier persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="test" >
<class>com.misha.model.Table1</class>
</persistence-unit>
</persistence>
Voici mon implémentation de service:
@Service("manService")
public class SaveManImpl implements SaveMan {
//
@Autowired
private ManRepositoryImpl manRepo;
@Transactional
public Table1 save(Table1 table) {
manRepo.save(table);
return null;
}
}
Et enfin mon implémentation Repository:
@Repository("manRepository")
public class ManRepositoryImpl implements ManRepository {
@PersistenceContext
private EntityManager em;
public Table1 save(Table1 table){
em.persist(table);
em.flush();
return table;
}
}
À l'exception de Spring, Spring ne peut pas voir l'annotation @Transactional, ai-je raison? J'ai essayé de mettre l'annotation au-dessus de la méthode de sauvegarde du référentiel, aucun résultat, après cette méthode de sauvegarde du service ci-dessus, la même chose ici. Merci d'avance
J'appelle la méthode de sauvegarde dans mon contrôleur
package com.misha.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import com.misha.model.Table1;
import com.misha.service.SaveMan;
@Controller
public class ManController {
@Autowired
SaveMan saveMan; // this is service interface
@RequestMapping(value="/test1")
public String saveMan(){
Table1 tab = new Table1();
tab.setName("name");
saveMan.save(tab);
return "saveMan";
}
}
Pile d'erreur:
SEVERE: Servlet.service() for servlet [fitTrackerServlet] in context with path [/test] threw exception [Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress] with root cause
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.Java:1171)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.Java:1332)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.Java:365)
at com.Sun.proxy.$Proxy20.flush(Unknown Source)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.Java:240)
at com.Sun.proxy.$Proxy20.flush(Unknown Source)
at com.misha.repository.ManRepositoryImpl.save(ManRepositoryImpl.Java:21)
at com.misha.service.SaveManImpl.save(SaveManImpl.Java:19)
at com.misha.controllers.ManController.saveMan(ManController.Java:21)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at Java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.Java:175)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.Java:421)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.Java:409)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:774)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:725)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:291)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
at org.Apache.Tomcat.websocket.server.WsFilter.doFilter(WsFilter.Java:52)
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:239)
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:206)
at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:219)
at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:106)
at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:501)
at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:142)
at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:79)
at org.Apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.Java:610)
at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:88)
at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:537)
at org.Apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.Java:1085)
at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:658)
at org.Apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.Java:222)
at org.Apache.Tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.Java:1556)
at org.Apache.Tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.Java:1513)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.Apache.Tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.Java:61)
at Java.lang.Thread.run(Unknown Source)
Fichier de configuration Spring
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<mvc:annotation-driven />
<!--<mvc:resources location="pdfs" mapping="/pdfs/**" />
<mvc:resources location="/resources" mapping="/resources/**"/> -->
<context:component-scan base-package="com.misha.controllers"></context:component-scan>
<context:component-scan base-package="com.misha.repository" />
<context:component-scan base-package="com.misha.service" />
<context:annotation-config/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
<property name="order" value="0"></property>
</bean>
<bean id="contentNegotiatingViewResolver"
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="request" value="text/html" />
</map>
</property>
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="defaultViews">
<list>
</list>
</property>
</bean>
<bean class="org.springframework.context.support.ResourceBundleMessageSource" >
<property name="basename" value="WEB-INF/messages"></property>
</bean>
</beans>
Vous avez deux contextes Spring:
le principal, configuré par jpaContext.xml, où les beans des packages de service et de référentiel sont analysés et mandatés par un intercepteur transactionnel.
celui mvc, configuré par l'autre fichier xml (vous ne l'avez pas nommé) dont le rôle est de décrire la partie MVC de l'application, c'est-à-dire définir et configurer par exemple les beans contrôleur, le résolveur de vue, etc. Ce contexte est un enfant du principal.
Le problème est que vous analysez également les packages de service et de référentiel dans ce contexte enfant. Vous vous retrouvez ainsi avec deux instances de chaque service et référentiel:
Le contrôleur est ainsi injecté avec un service provenant du même contexte que le contrôleur: le non transactionnel.
Pour confirmer cela, vous pouvez ajouter des traces dans le constructeur des beans et voir combien de fois elles sont instanciées.
Et pour éviter le problème, il existe deux solutions:
Vous devez présenter votre gestionnaire d'entités à votre gestionnaire de transactions, de sorte que lorsque vous annotez votre fonction avec @Transactional
it charge les instances du pool
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />
HTH!
Pour faire court, essayez d'ajouter @Transactional
au tout début de votre méthode. C'était un problème dans mon cas.