我在Hibernate上通过JPA使用Spring Boot 1.2.3.RELEASE版本。我遇到以下异常
org.springframework.dao.InvalidDataAccessApiUsageException: No transactional EntityManager available; nested exception is javax.persistence.TransactionRequiredException: No transactional EntityManager available at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:410) ~[EntityManagerFactoryUtils.class:4.1.6.RELEASE] at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223) ~[HibernateJpaDialect.class:4.1.6.RELEASE] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) ~[AbstractEntityManagerFactoryBean.class:4.1.6.RELEASE] at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[ChainedPersistenceExceptionTranslator.class:4.1.6.RELEASE] at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[DataAccessUtils.class:4.1.6.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) ~[PersistenceExceptionTranslationInterceptor.class:4.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE] at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122) ~[CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.class:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [ExposeInvocationInterceptor.class:4.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [JdkDynamicAopProxy.class:4.1.6.RELEASE] at com.sun.proxy.$Proxy110.deleteByCustomerId(Unknown Source) ~[na:na] Caused by: javax.persistence.TransactionRequiredException: No transactional EntityManager available at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:275) ~[SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.class:4.1.6.RELEASE] at com.sun.proxy.$Proxy102.remove(Unknown Source) ~[na:na] at org.springframework.data.jpa.repository.query.JpaQueryExecution$DeleteExecution.doExecute(JpaQueryExecution.java:270) ~[JpaQueryExecution$DeleteExecution.class:na] at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:74) ~[JpaQueryExecution.class:na] at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:97) ~[AbstractJpaQuery.class:na] at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:88) ~[AbstractJpaQuery.class:na] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:395) ~[RepositoryFactorySupport$QueryExecutorMethodInterceptor.class:na] at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:373) ~[RepositoryFactorySupport$QueryExecutorMethodInterceptor.class:na]
以下是我的程序结构 Configuration类
@Configuration @ComponentScan @EnableAutoConfiguration @EnableTransactionManagement public class WSApplication { public static void main(final String[] args) { SpringApplication.run(WSApplication.class, args); } } @Entity @Table(Orders) public class Order { @id @GeneratedValue private long id; @Column(name = "customerId") private Long customerId; // getter & setter methods // equals & hashCode methods } public interface OrderRepository extends JpaRepository<Order, Long> { List<Order> findByCustomerId(Long customerId); // 4- @Transactional works fine void deleteByCustomerId(Long cusotmerId); } public class OrderService { @Autowired private OrderRepository repo; // 3- @Transactional works fine public void deleteOrder(long customerId){ //1- throws exception repo.deleteByCustomerId(customerId); //2- following works fine //repo.delete(repo.findByCustomerId(customerId).get(0)); } }
在上面的服务类代码中,谁能指导我为什么2起作用而1抛出异常。
谢谢
首先,我引用Spring-Data JPA文档来说明为什么该delete方法在您的情况下有效(我的意思是选项 2 )。
delete
默认情况下,存储库实例上的CRUD方法是事务性的。对于读取操作,将事务配置readOnly标志设置为true,所有其他标志都配置为纯文本,@Transactional以便应用默认事务配置。有关详细信息,请参见CrudRepository的JavaDoc。
readOnly
@Transactional
该delete方法实际上是的方法CrudRepository。您的存储库JpaRepository可以扩展CrudRespository,而扩展则可以扩展,因此它属于CrudRepository接口,并且根据上面的引用是事务性的。
CrudRepository
JpaRepository
CrudRespository
如果阅读了“ 事务性查询方法 ”一节,您将看到与选项 4 相同的内容,并且您将知道如何对存储库的所有方法应用自定义事务行为。此外,文档的 示例61 显示了与选项 3 相同的场景。
现在请记住,您不是在使用JDBC逻辑,在这种情况下,数据库会处理事务,但要在基于ORM的框架中进行。ORM框架需要事务才能触发对象高速缓存和数据库之间的同步。因此,您必须了解并为执行ORM逻辑的方法提供事务上下文deleteByCustomerId。
deleteByCustomerId
默认情况下@Transactional(我的意思是没有任何参数)将传播模式设置REQUIRED为false,将readOnly标志设置为false。调用其中注释的方法时,如果不存在任何事务,则会初始化事务。这就是为什么的原因, 解决办法 @LucasSaldanha的(同例如 使用一个门面来定义多个库调用交易 )和选项 4个 作品。否则,如果没有事务,您将陷入选项 1 的抛出异常。
REQUIRED