我正在使用 Spring Boot 1.2.3.RELEASE 版本和 JPA over hibernate。我遇到以下异常
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
@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 抛出异常。
Thanks
首先,我引用一下Spring-Data JPA 文档 http://docs.spring.io/spring-data/jpa/docs/current/reference/html/来证明为什么delete
方法适用于你的情况(我的意思是选项2).
默认情况下,存储库实例上的 CRUD 方法是事务性的。为了
读取操作交易配置readOnly
标志已设置
为 true,所有其他都配置为普通@Transactional
以便
应用默认事务配置。详细信息请参阅 JavaDoc
Crud存储库
The delete
方法实际上是一个方法CrudRepository
。您的存储库扩展JpaRepository
这延伸了CrudRespository
,所以它属于 CrudRepository 接口,并且根据上面的引用是事务性的。
如果您阅读了该部分事务查询方法 http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactional-query-methods你会看到它与选项相同4您将了解如何为存储库的所有方法应用自定义事务行为。
另外,实施例61文档显示了与该选项相同的场景3.
现在请记住,您不是在使用 JDBC 逻辑(在这种情况下,数据库会处理事务),而是在基于 ORM 的框架内进行操作。 ORM 框架需要事务来触发对象缓存和数据库之间的同步。
因此,您必须了解并为执行 ORM 逻辑的方法提供事务上下文,例如deleteByCustomerId
.
默认情况下@Transactional
(我的意思是没有任何参数)将传播模式设置为REQUIRED
并将 readOnly 标志设置为 false。当您调用其中注释的方法时,如果不存在事务,则会初始化事务。这就是为什么解决方法@LucasSaldanha(与示例相同使用外观来定义多个存储库调用的事务)和选项4作品。否则,如果没有交易,你就会陷入期权抛出的异常1.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)