Je reçois cette erreur lorsque j'appelle la méthode "persist" pour enregistrer le modèle d'entité dans une base de données dans mon application Web Spring MVC. Impossible de trouver vraiment un message ou une page sur Internet pouvant être en relation avec cette erreur particulière. Il semble que quelque chose ne va pas avec le bean EntityManagerFactory, mais je suis assez nouveau dans la programmation Spring, donc pour moi, tout semble être initialisé correctement et selon divers articles de tutoriel sur le Web.
dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/data/repository
http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">
<context:component-scan base-package="wymysl.Controllers" />
<jpa:repositories base-package="wymysl.repositories"/>
<context:component-scan base-package="wymysl.beans" />
<context:component-scan base-package="wymysl.Validators" />
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
<bean id="passwordValidator" class="wymysl.Validators.PasswordValidator"></bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="Oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:Oracle:thin:@localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="polskabieda1" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
</props>
</property>
</bean>
<mvc:annotation-driven />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
</bean>
<bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/resources/*" location="/resources/css/"
cache-period="31556926"/>
</beans>
RegisterController.Java
@Controller
public class RegisterController {
@PersistenceContext
EntityManager entityManager;
@Autowired
PasswordValidator passwordValidator;
@InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(passwordValidator);
}
@RequestMapping(value = "/addUser", method = RequestMethod.GET)
public String register(Person person) {
return "register";
}
@RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String register(@ModelAttribute("person") @Valid @Validated Person person, BindingResult result) {
if(result.hasErrors()) {
return "register";
} else {
entityManager.persist(person);
return "index";
}
}
J'ai eu le même problème et j'ai annoté la méthode comme @Transactional
et cela a fonctionné.
UPDATE: en vérifiant la documentation print, il semble que PersistenceContext soit par défaut de type Transaction. C'est pourquoi la méthode doit être transactionnelle ( http://docs.spring.io/spring/docs/current/spring- framework-reference/html/orm.html ):
L'annotation @PersistenceContext a un type d'attribut facultatif, qui par défaut est PersistenceContextType.TRANSACTION. Cette valeur par défaut correspond à ce dont vous avez besoin pour recevoir un proxy EntityManager partagé. L’alternative, PersistenceContextType.EXTENDED, est une affaire complètement différente: il en résulte un EntityManager étendu, qui n’est pas thread-safe et ne doit donc pas être utilisé dans un composant accédé simultanément tel qu'un bean singleton géré par Spring. Les EntityManagers étendus ne sont supposés être utilisés que dans des composants avec état qui, par exemple, résident dans une session, le cycle de vie de EntityManager n'étant pas lié à une transaction en cours, il dépend entièrement de l'application.
J'ai eu cette exception en essayant d'utiliser une méthode personnalisée deleteBy dans le référentiel de données Spring. L'opération a été tentée à partir d'une classe de test JUnit.
L'exception ne se produit pas lors de l'utilisation de l'annotation @Transactional
au niveau de la classe JUnit.
Cette erreur m'a rongé pendant trois jours, la situation à laquelle j'ai été confronté a produit la même erreur. Après tous les conseils que j'ai pu trouver, j'ai joué avec la configuration, mais en vain.
Finalement, j'ai trouvé que la différence, le service que j'exécutais était contenu dans un pot commun, le problème s'est avéré être AspectJ ne traitant pas l'instanciation du service de la même manière. En réalité, le proxy appelait simplement la méthode sous-jacente sans que toute la magie Spring normale soit exécutée avant l'appel de la méthode.
Finalement, l'annotation @Scope placée sur le service conformément à l'exemple a résolu le problème:
@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
@Transactional
public class CoreServiceImpl implements CoreService {
@PersistenceContext
protected EntityManager entityManager;
@Override
public final <T extends AbstractEntity> int deleteAll(Class<T> clazz) {
CriteriaDelete<T> criteriaDelete = entityManager.getCriteriaBuilder().createCriteriaDelete(clazz);
criteriaDelete.from(clazz);
return entityManager.createQuery(criteriaDelete).executeUpdate();
}
}
La méthode que j'ai publiée est une méthode de suppression, mais les annotations affectent toutes les méthodes de persistance de la même manière.
J'espère que ce message aidera quelqu'un qui a eu des difficultés avec le même problème lors du chargement d'un service depuis un bocal
J'ai eu la même erreur parce que je suis passé de la configuration XML à la configuration Java.
Le fait était que je n’ai pas migré la balise <tx:annotation-driven/>
, comme l’a suggéré Stone Feng.
Je viens donc d'ajouter @EnableTransactionManagement
comme suggéré ici Configuration de transactions basées sur des annotations au printemps dans la classe @Configuration , et cela fonctionne maintenant.
J'ai eu le même problème et j'ai ajouté tx:annotation-driven
dans applicationContext.xml
et cela a fonctionné.
boardRepo.deleteByBoardId (id);
Face au même problème. GOT javax.persistence.TransactionRequiredException: aucun EntityManager avec transaction réelle disponible pour le thread actuel
Je l'ai résolu en ajoutant @ Transactional annotation au-dessus du contrôleur/service.
La même erreur s'est produite lors de l'accès à une méthode déjà annotée de transaction à partir d'une méthode non transactionnelle au sein du même composant:
Before:
@Component
public class MarketObserver {
@PersistenceContext(unitName = "maindb")
private EntityManager em;
@Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
public void executeQuery() {
em.persist(....);
}
@Async
public void startObserving() {
executeQuery(); //<-- Wrong
}
}
//In another bean:
marketObserver.startObserving();
J'ai corrigé l'erreur en appelant executeQuery () sur le composant auto-référencé:
Fixed version:
@Component
public class MarketObserver {
@PersistenceContext(unitName = "maindb")
private EntityManager em;
@Autowired
private GenericApplicationContext context;
@Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
public void executeQuery() {
em.persist(....);
}
@Async
public void startObserving() {
context.getBean(MarketObserver.class).executeQuery(); //<-- Works
}
}
Pour nous, le problème était lié aux mêmes paramètres de contexte dans plusieurs fichiers de configuration. Vérifiez que vous n'avez pas dupliqué les éléments suivants dans plusieurs fichiers de configuration.
<context:property-placeholder location="classpath*:/module.properties"/>
<context:component-scan base-package="...." />
J'avais le même code d'erreur lorsque j'ai utilisé @Transaction
sur une méthode/un niveau d'action incorrect.
methodWithANumberOfDatabaseActions() {
methodA( ...)
methodA( ...)
}
@Transactional
void methodA( ...) {
... ERROR message
}
Je devais placer le @Transactional
juste au-dessus de la méthode methodWithANumberOfDatabaseActions()
, bien sûr.
Cela a résolu le message d'erreur dans mon cas.
J'avais ce problème depuis des jours et rien que je n'ai trouvé nulle part en ligne ne m'aidait, je publie ma réponse ici au cas où cela aiderait quelqu'un d'autre.
Dans mon cas, je travaillais sur un microservice appelé par le biais de la communication à distance, et mon annotation @Transactional au niveau du service n'était pas capturée par le proxy distant.
Ajouter une classe de délégué entre les couches service et dao et marquer la méthode de délégué comme étant transactionnelle a résolu ce problème.
J'ai enlevé le mode de
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
faire ce travail