Spring boot + Hibernate + JPA No transactional EntityManager available

前端 未结 3 1936
再見小時候
再見小時候 2021-02-07 08:43

I am using spring boot 1.2.3.RELEASE version with JPA over hibernate. I am experiencing following exception

org.springframework.dao.InvalidDataAccessApiUsageExce         


        
相关标签:
3条回答
  • 2021-02-07 09:04

    First, I make a quote of the Spring-Data JPA Documentation to justify why the delete method works in your case (I mean the option 2).

    CRUD methods on repository instances are transactional by default. For reading operations the transaction configuration readOnly flag is set to true, all others are configured with a plain @Transactional so that default transaction configuration applies. For details see JavaDoc of CrudRepository

    The delete method is actually a method of the CrudRepository. Your repository extends JpaRepository which extends CrudRespository, so it belongs to CrudRepository interface and according the quote above is transactional.

    If you read the section Transactional Query Method you will see that is the same that the option 4 and you will know how to apply a custom transactional behavior for all methods of your repository. Also, the Example 61 of the documentation shows the same scenario that the option 3.

    Now keep in mind that you aren't working with JDBC logic, in which case the database take care about the transactions, but within a ORM-based framework. ORM frameworks require a transaction in order to trigger the synchronization between the object cache and the database. So you must be aware and provide a transaction context for methods that do ORM logic like deleteByCustomerId.

    By default @Transactional (I mean without any parameter) set propagation mode to REQUIREDand readOnly flag to false. When you invoke a method annotated within, a transaction is intialized if no-one exists. This is the reason of why the workaround of @LucasSaldanha (the same as example Using a facade to define transactions for multiple repository calls) and the option 4 works. Other wise, without a transaction, you fall in the thrown exception of the option 1.

    0 讨论(0)
  • 2021-02-07 09:08

    Ok I found out a way of making it works.

    Just put a @Transactional annotation (org.springframework.transaction.annotation.Transactional) in your deleteOrder method at OrderService.

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

    I really don't know why the second works. I guessing that since it is an direct method from the CrudRepository interface someway it knows how to execute it atomically.

    The former one is a call to the deleteByCustomerId. This call will be processed to find out the customer with the specified id and then deletes it. For some reason it makes the use of an explicit transaction.

    Again it is just a guess. I'll try to contact some spring developers and maybe open a issue to verify this behaviour.

    Hope it helps!

    Reference: http://spring.io/guides/gs/managing-transactions/

    0 讨论(0)
  • 2021-02-07 09:10

    I still got the No transactional EntityManager available exception even after annotating my search() method with @Transactional.

    I followed this tutorial which describes how to set up Hibernate search in Spring Boot.

    The issue for me was that I had a different dependency on hibernate-search-orm. The dependency which worked for me without any problems was

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

    After adding this to the gradle build file, everything worked as expected.

    Hope this helps someone else as well.

    0 讨论(0)
提交回复
热议问题