简体   繁体   中英

Spring Data JPA + Hibernate Marking methods as Transactional

I am using Spring data JPA's repository for my application. Currently I am using basic CRUD operations provided by default by spring data jpa repositories and for complex join queries, I am writing custom JPQL queries as follows:

public interface ContinentRepository extends JpaRepository<Continent, Long>
{
    @Query(value = "SELECT u FROM Continent u JOIN FETCH ... WHERE u.id = ?1")
    public List<Continent> findContinent(Long id);
}

In my Service class, I am autowiring this repository and performing DB operations.

@Service
public class MyService
{
    @Autowired
    public ContinentRepository cr;

    public void read()
    {
        var result1 = cr.findContinent(1);
        var result2 = cr.findContinent(2);
    }


    @Transactional
    public void write()
    {
        var c = new Continent();
        // setters
        c = cr.save(c);
    }
}

Currently I am just marking the write() as org.springframework.transaction.annotation.Transactional .

  1. Should I also mark read() method with Transactional(readOnly = true) ? As it only performs read operations.
  2. Should I also mark the findContinent(Long id) as Transactional(readOnly = true)? I read that all the default methods as marked as Transactional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions
  3. In the repository interface, should I mark the Transactional annotation at the method level or at the interface level. (Also, I suspect most of the custom methods will be read only)
  4. Is it good to have @Transactional at both Service and Repository layer?
  1. Should I also mark read() method with Transactional(readOnly = true)? As it only performs read operations.

Not really necessary, however it might create some optimisations regarding cache memory consumption accordingly to this blog https://vladmihalcea.com/spring-read-only-transaction-hibernate-optimization/

  1. Should I also mark the findContinent(Long id) as Transactional(readOnly = true)? I read that all the default methods as marked as Transactional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions

The same answer like in the first case

  1. In the repository interface, should I mark the Transactional annotation at the method level or at the interface level. (Also, I suspect most of the custom methods will be read only)

In general I added to the method level, because I have more control over the parameters like rollback

  1. Is it good to have @Transactional at both Service and Repository layer?

I recommend you to have at the Service level because, there, you can update many tables (so you can use many repositories), and you want your entire update to be transactional.

  1. Should I also mark read() method with Transactional(readOnly = true)? As it only performs read operations.

Yes. It is good practice, you will know immediately that this method doesn't change anything in database, and what is more important, you will disable some unintentional changes in database using this service method. If this method tries to do any update on DB exception will be thrown and rollback will be called.

  1. Should I also mark the findContinent(Long id) as Transactional(readOnly = true)? I read that all the default methods as marked as Transactional https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions

Depends how you are using it. If you are always calling this from @Sevice then no. I think that is common use case as fare as I know.

  1. In the repository interface, should I mark the Transactional annotation at the method level or at the interface level. (Also, I suspect most of the custom methods will be read only)

Same as 2.

  1. Is it good to have @Transactional at both Service and Repository layer?

Same as 2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM