2015-10-31 67 views
1

設計了包含@Transactional方法的Service方法後,我遇到了「沒有事務性EntityManager可用」的問題。 Technogoly用途:JPA,春,Maven的TransactionRequiredException:在@Transactional方法中沒有可用的事務性EntityManager

異常堆棧跟蹤

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) 

我在主調用服務的方式:

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); 
    }  
} 

OrderDAOImpelementation與方法saveOrder(訂單順序)是與在ItemDAO(堅持()/合併())

預先感謝任何命題

+0

發佈完整的異常堆棧跟蹤。向我們展示如何獲得服務的實例。並使用單個元素,並使用這兩個屬性。 –

+0

感謝您的回答,但沒有更改將參數變爲單個字段 – ryzhman

+0

您的問題與TransactionRequiredException有關。發佈該異常的堆棧跟蹤。不是無關異常的堆棧跟蹤。 –

回答

0

Your're主叫

OrderDAOImpl.saveOrder(); 

從方法

DeliveryStaffServiceImpl.changeStatusOfOrder(); 

,但在這個例子中,你表明@Transactional註釋放在一個n無關的方法KitchenStaffServiceImpl.processItem()。最有可能的是,您需要DeliveryStaffServicleImpl上的@Transactional註釋。

+0

準確!非常感謝! – ryzhman

相關問題