当前位置: 首页 > 知识库问答 >
问题:

Spring boot Hibernate JPA无可用的事务实体管理器

越朗
2023-03-14

我正在使用Spring boot 1.2.3。JPA的发布版本超过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个抛出异常。

谢啦

共有3个答案

弘浩瀚
2023-03-14

即使用@transactional注释了我的search()方法,我仍然得到了“无可用的事务实体管理器”(No transactional EntityManager)异常。

我遵循了这个教程,它描述了如何在Spring Boot中设置Hibernate搜索。

我的问题是,我对hibernate search orm有不同的依赖性。对我来说没有任何问题的依赖是

compile("org.hibernate:hibernate-search-orm:5.7.0.Final")

将其添加到gradle构建文件后,一切都按预期进行。

希望这对其他人也有帮助。

麻宾白
2023-03-14

好吧,我找到了一种方法让它发挥作用。

只需在OrderService的deleteorder方法中放入@Transactional注释(org.springframework.transaction.annotation.Transactional)。

@Transactional
public void deleteOrder(long customerId){
    repo.deleteByCustomerId(customerId);
}

我真的不知道为什么第二个有效。我猜,因为它是来自CrudRepository接口的直接方法,所以它知道如何以原子方式执行它。

前者是对deleteByCustomerId的调用。将处理此调用以找出具有指定id的客户,然后将其删除。出于某种原因,它使用显式事务。

这只是一个猜测。我将尝试联系一些spring开发人员,并可能打开一个问题来验证这种行为。

希望有帮助!

参考:http://spring.io/guides/gs/managing-transactions/

督翰学
2023-03-14

首先,我引用了Spring-Data JPA文档来证明为什么delete方法在您的情况下有效(我指的是选项2)。

默认情况下,存储库实例上的CRUD方法是事务性的。对于读取操作,事务配置readOnly标志设置为true,其他所有事务都使用普通事务配置进行配置,以便应用默认事务配置。有关详细信息,请参阅CrudRepository的JavaDoc

delete方法实际上是CrudRepository的一种方法。您的存储库扩展了JpaRepository,它扩展了CrudRespository,因此它属于CrudRepository接口,根据上面的引用是事务性的。

如果您阅读Transactional Query Method部分,您将看到与选项4相同,并且您将知道如何为存储库的所有方法应用自定义事务行为。此外,留档的示例61显示了与选项3相同的场景。

现在请记住,您不是在使用JDBC逻辑,在这种情况下,数据库负责事务,而是在基于ORM的框架内。ORM框架需要一个事务来触发对象缓存和数据库之间的同步。因此,您必须了解并为执行ORM逻辑的方法提供事务上下文,如deleteByCustomerId。

默认情况下,事务性(我的意思是没有任何参数)将传播模式设置为所需,只读标志设置为false。当您调用在中注释的方法时,如果不存在任何事务,则事务将被初始化。这就是为什么@LucasSaldanha的解决方案(与使用facade定义多个存储库调用的事务的示例相同)和选项4可以工作的原因。另一方面,如果没有事务,则属于抛出的选项1异常。

 类似资料:
  • 在我的实际应用程序中,我有一个业务层,它根据一些业务规则使用JPA来持久化数据,问题是camel JPA事务没有与业务层事务共享。我需要业务类中的EntityManager与Camel事务范围集成,我该怎么做? 下面是一个简单的例子,但这反映了实际设计中的问题。 项目实例 服务级别 骆驼路线 骆驼背景。xml

  • 我正在使用Spring的事务支持和JPA(Hibernate)来持久化我的实体。一切正常,但我在处理一个请求中的部分更新时陷入困境: 对于每个用户(HTTP)请求,我必须将一个日志条目写入数据库表,即使“主”业务实体的更新失败(例如,由于验证错误)。因此,我的第一个/主要事务get被回滚,但第二个(写日志)应该提交。这似乎可以使用正确的传播级别来写入日志条目: 然而,我的问题是,我在第二个事务中注

  • 我想发出POST请求以将用户保存到我的Oracle DB中。 我在jpa和hibernate中使用Spring MVC。 这是我的jpaContext.xml 这是我的UserRepoImpl类: 这是UserServiceImpl类: 这是来自REST控制器的方法: 我在服务图层上有注释。我尝试了许多在线找到的解决方案,使用存储库层上的@Transactional,或者使用@Scope(prox

  • 我试图从注入的EntityManager中打开Hibernate会话,因为我需要使用Hibernate的原生标准API。 当我尝试使用标准时,我得到以下异常: 但是,当我使用EntityManager本身的Query api时,一切都很好。 我的配置: db.xml PouzivatelDAOHibernate 不起作用: PouzivatelDAOHibernate,它确实工作: 编辑:我在JP

  • 我试图使用spring boot将EntityManager注释注入到我的DAO中,但是得到一个< code > InvalidDataAccessApiUsageException 消息,说没有可用的事务EntityManager。我的印象是,只要Spring Boot从< code>application.yml中获得了我的数据源信息,并且我用< code>@PersitenceContext