Reputation: 979
I am still trying to wrap my head around how @Transactional works.
I have @Transactional
annotation on Service class's method and @Modifying
annotation on the method in the Repository class. Does method with @Transactional
annotation applies to the method in the Repository with annotation @Modifying
?
My understanding:
@Transactional
on a method of a class with@Transactional( readOnly = true )
no data gets written to the database, whereas with@Transactional
, the data gets written to the database.
Modifying Queries
- Modifying method signature can only return
void
,Integer
orint
- Updating queries MUST be transactional, mark with
@Transactional
- Spring Data will drop all non-flushed changes pending in the
EntityManager
, change with@Modifying(clearAutomatically=false)
As the second point says @Modifying
queries must have @Transactional(readOnly=false)
, so we can either add it at @Service
level method call or @Repository
method level call. If added at the @Service
level it applies to the @Respository
method too which is being called from the @Service
level method call?
Example:
@Service
class AnimalServiceImpl implements AnimalService {
@Autowire
AnimalRepository animalRepository;
@Override
@Transactional
public void persistAnimal() {
....
animalRepository.save();
}
@Override
@Transactional(readOnly = true)
public void checkIfAnimalPresent() {
...
animalRepository.checkIfPresent();
}
@Override
@Transactional
public void deleteAnimal() {
...
animalRepository.deleteAnimal();
}
}
Repository
@Repository
@Transactional(readOnly=true)
public interface AnimalRepository extends org.springframework.data.repository.Repository {
@Modifying
@Query(...)
void save();
@Modifying
@Query(...)
int checkIfPresent()
@Modifing
@Query(..)
int deleteAnimal();
}
My question is around:
@Transactional
in the service class when we have it at the repository @Repository
level and I have @Modifying
on methods
which modify the entity and writes it to the database (only because I have @Transactional(readOnly = true)
at the class level) ?@Transactional
on the Service class propogate to @Repository
class?I hope I am very clear with my questions and examples here.
Upvotes: 21
Views: 36395
Reputation: 196
This how @Transactional
works:
By default, CRUD methods on repository instances are transactional.
For read operations, the transaction configuration readOnly
flag is set to true
.
All others are configured with a plain @Transactional
so that default transaction configuration applies.
If you need to tweak transaction configuration for one of the methods declared in a repository you can override that method and add @Transactional
annotation with required attribute values.
Another way to alter transactional behavior is to use a facade or service implementation that (typically) covers more than one repository.
Its purpose is to define transactional boundaries for non-CRUD operations.
If you use this approach, the transaction configuration at the repositories is then neglected, as the outer transaction (defined in the service layer) configuration determines the actual one used.
Reference: Spring Data JPA - Reference Documentation - 5.7. Transactionality
Upvotes: 18