【问题标题】:TransactionRequiredException: No transactional EntityManager available within @Transactional methodTransactionRequiredException:@Transactional 方法中没有可用的事务性 EntityManager
【发布时间】:2016-01-31 21:20:03
【问题描述】:

设计了包含@Transactional 方法的Service 方法后,我遇到了“没有可用的事务EntityManager”的问题。 Technogoly 使用:JPA、Spring、Maven

异常堆栈跟踪

Exception in thread "main" javax.persistence.TransactionRequiredException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:273)
at com.sun.proxy.$Proxy29.merge(Unknown Source)
at com.restaurant.DAO.OrderDAOImpl.saveOrder(OrderDAOImpl.java:24)
at com.restaurant.services.DeliveryStaffServiceImpl.changeStatusOfOrder(DeliveryStaffServiceImpl.java:37)
at com.restaurant.entities.Main.main(Main.java:161)

我在main中调用服务的方式:

DeliveryStaffService del = context.getBean(DeliveryStaffService.class);
    List<Order> listOfOrders = del.getListOfOrders();

试图找出问题:

  1. 在 pom.xml 中检查 Spring 的版本;
  2. 检查是否所有@transactional方法都是公开的;
  3. 在 beans.xml 中添加
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

此外,在同一个项目中有一些带有@transactional 方法的服务,它们可以正常工作。

这是我的 persistence.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<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"
xmlns="http://java.sun.com/xml/ns/persistence"  version="2.0" >
    <persistence-unit name="Restaurant" transaction-type="RESOURCE_LOCAL">
        <provider>
             org.eclipse.persistence.jpa.PersistenceProvider
        </provider>
    <properties>
            <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:derby:..//RestaurantDB1;create=true" />
            <property name="eclipselink.ddl-generation.output-mode" value="database" />
                 <property name="eclipselink.weaving" value="static" />
    </properties>
    </persistence-unit>
 </persistence> 

Beans.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-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="com.restaurant"/>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="packagesToScan" value="com.restaurant"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="persistenceUnitName" value="Restaurant"/>

        <property name="jpaDialect"> 
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/> 
        </property> 

        <property name="jpaVendorAdapter"> 
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
                <property value="true" name="showSql"/> 
                <property value="true" name="generateDdl"/>
                <property name="databasePlatform" value="org.eclipse.persistence.platform.database.DerbyPlatform"/> 
            </bean> 
        </property>

        <property name="jpaPropertyMap">
            <map>
              <entry key="eclipselink.weaving" value="false" />
            </map>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
          <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    </bean>

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

    <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"/>
        <property name="url" value="jdbc:derby:..//RestaurantDB1;create=true" /> 
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/> 
    <tx:annotation-driven proxy-target-class="true"/> 
</beans>

服务实现

 @Named
public class KitchenStaffServiceImpl implements KitchenStaffService {

    @Inject
    private ItemDAO itemDAO;
    @Inject
    private OrderDAO orderDAO;

    @Override
    public List<Item> viewItems() {
        return itemDAO.viewItems();
    }

    @Override
    @Transactional
    public void processItem(Item item) {
        int i=item.getQuantity();
        while(i>0){
            try {
                Thread.sleep(1000);
                --i;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        item.setIsCooked(true);
        itemDAO.saveItem(item);
        System.out.println(item.getId());

        List<Item> list = item.getOrder().getListOfDishes();
        if(list.stream().allMatch(t -> t.getIsCooked()==true)){
            Order ord = item.getOrder();
            ord.setStatus(StatusOfDelivery.READY_FOR_SHIPMENT);
            orderDAO.saveOrder(ord);
        }
    }
}

DAO 实现

    @Repository
public class ItemDAOImpl implements ItemDAO{

    @PersistenceContext
    private EntityManager em; 

    @Override
    public void saveItem(Item item){
        if(item.getId()==0){
            em.persist(item);
        }else
            em.merge(item);
    }       
}

使用 saveOrder(Order order) 方法的 OrderDAOImpelementation 与 ItemDAO 中的相同 (persist()/merge())

提前感谢任何建议

【问题讨论】:

  • 发布完整的异常堆栈跟踪。向我们展示您如何获取服务实例。并使用具有两个属性的单个 元素。
  • 感谢您的回答,但将 参数合并到单个字段没有任何变化
  • 您的问题是关于 TransactionRequiredException。发布该异常的堆栈跟踪。不是无关异常的堆栈跟踪。
  • 我可以看到,您的 stracktrace 中唯一的异常是 SyntaxErrorExceptions。所以你应该检查你的查询。
  • 天啊!对不起,我今天工作了很多小时,并发布了项目另一部分的异常。已经更新了堆栈跟踪

标签: java spring jpa persistence


【解决方案1】:

你来电

OrderDAOImpl.saveOrder();

从方法

DeliveryStaffServiceImpl.changeStatusOfOrder();

但在示例中,您显示 @Transactional 注释放在不相关的方法 KitchenStaffServiceImpl.processItem() 上。很可能,您需要 DeliveryStaffServicleImpl 上的 @Transactional 注释。

【讨论】:

  • 没错!非常感谢!
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-16
相关资源
最近更新 更多