javax.persistence.TransactionRequiredException:没有可用的事务性 EntityManager
Posted
技术标签:
【中文标题】javax.persistence.TransactionRequiredException:没有可用的事务性 EntityManager【英文标题】:javax.persistence.TransactionRequiredException: No transactional EntityManager available 【发布时间】:2015-01-15 09:37:39 【问题描述】:从昨天开始,我一直在与这个异常作斗争...我检查了几乎所有内容,搜索了所有链接,但一无所获。
当我从类别服务调用 addCategory 或 removeCategory 时,我总是收到异常 javax.persistence.TransactionRequiredException: No transactional EntityManager available。我附上了所有必要的配置文件。
我想让 Spring 处理事务。
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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.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-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.example" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="punit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"></property>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.mysql5InnoDBDialect"></entry>
<entry key="hibernate.hbm2ddl.auto" value="create-drop"></entry>
<entry key="hibernate.format_sql" value="true"></entry>
</map>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/shopify?autoReconnect=true" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
</beans>
persistence.xml - 在 /META-INF/
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="punit">
</persistence-unit>
</persistence>
web.xml - 片段,我在其中加载上下文
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/jpaContext.xml
/WEB-INF/security-config.xml
</param-value>
</context-param>
分类服务
package com.example.service;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.dao.CategoryDao;
import com.example.Category;
@Service
public class CategoryService
@Autowired
@Qualifier("categoryDaoDatabase")
private CategoryDao categoryDao;
@Transactional
public void addCategory(Category category)
category.setId(getLastCategoryId() + 1);
categoryDao.addCategory(category);
@Transactional
public void removeCategory(Category category)
categoryDao.removeCategory(category);
public void setCategoryDao(CategoryDao categoryDao)
this.categoryDao = categoryDao;
类道
package com.example.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import com.example.domain.Category;
@Repository
public class CategoryDaoDatabase implements CategoryDao
@PersistenceContext
private EntityManager entityManager;
public void addCategory(Category category)
entityManager.persist(category);
entityManager.flush();
public void removeCategory(Category category)
entityManager.remove(category);
public void setEntityManager(EntityManager entityManager)
this.entityManager = entityManager;
Maven 依赖项 - pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.7.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.7.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
问候, 汤姆
编辑 - 解决方案
正如 M. Deinum 提供的解决方案,问题在于,我提出了
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
在 jpaContext.xml 中,我没有加载所有类(它们加载在 shopify-servlet.xml - 我的主要应用程序上下文中)。我将以上几行移到了我的主上下文(shopify-servlet.xml),在那里我进行了组件扫描,它扫描并将所有控制器、服务、存储库加载到主上下文,所以现在@Transactional 工作了:)。
【问题讨论】:
对于初学者来说,不要混合使用 Spring 的 4.1.0、4.1.1 和 4.1.4 的框架版本,不要。如果您有DispatcherServlet
,请确保您不再扫描相同的组件,因为这将导致重复的实例与最后一个没有应用 AOP。
我将所有内容设置为 4.1.0,然后设置为 4.1.4,我检查了所有依赖项。它仍然没有工作。这是我的 web.xml:pastebin.com/raw.php?i=k5KKbMms 顺便说一句。我仅在 shopify-servlet(主要上下文)上进行组件扫描
这基本上解释了你的问题。您的组件扫描应该与<tx;annotation-driven />
在同一个xml 中,否则不会发生任何事情。 AOP 仅适用于同一上下文中的 bean,而不适用于父上下文或子上下文。
另外,在进行组件扫描时,请确保您没有两次检测到组件,因为这将导致相同的错误。根据经验,您的 ContextLoaderListener
应该扫描除网络相关 bean 之外的所有内容(@COntroller
等),而您的 DispatcherServlet
应该只扫描网络相关 bean。
@M.Deinum 它正在工作!非常感谢你!! :) 我会将您的答案添加到我的问题中,因为它们非常有用:)。
【参考方案1】:
正如之前的一篇文章已经指出的那样 - 永远不要混合这样的版本。
您可以用来强制/锁定到一个固定版本,如果您使用简洁的“材料清单”(bom) 资源,您就无需在多个位置指定这样的版本(显然存在丢失某些内容的风险沿着轨道) - 此功能还可以删除依赖关系树中的任何传递依赖关系。
如果您还需要 spring-security,您可以将其锁定到 springframework v4.0.2.RELEASE - 根据 spring doco (http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#maven-bom) 的说法,这是已完全验证可与 spring-security 3.2.5.RELEASE 一起使用的最大版本。当您使用 bom 时,所有 spring-security 的 springframework v3.2.8.RELEASE 资源将自动被带到 spingframework v4.0.2.RELEASE。
【讨论】:
解决方案在哪里?以上是关于javax.persistence.TransactionRequiredException:没有可用的事务性 EntityManager的主要内容,如果未能解决你的问题,请参考以下文章