Issue
I am confused about @Transactional
annotation with base and subclasses. I have the following code with several generic subclasses derived from the base class CustomRepository<T>
which implements ICustomRepository<T>
. I want all the methods of the interface ICustomRepository<T>
be transactional.
// class ActivityCustomRepository.java
@Repository
public class ActivityCustomRepository extends CustomRepository<Activity> {
private static final String TABLE_NAME = "activity";
public ActivityCustomRepositoryImpl(ActivityRowMapperImpl rowMapper, JdbcTemplate jdbcTemplate) {
super(TABLE_NAME, rowMapper, jdbcTemplate);
}
// class PersonCustomRepository.java
@Repository
public class PersonCustomRepository extends CustomRepository<Person> {
private static final String TABLE_NAME = "person";
public PersonCustomRepository(PersonRowMapperImpl rowMapper, JdbcTemplate jdbcTemplate) {
super(TABLE_NAME, rowMapper, jdbcTemplate);
}
// CustomRepository.java
@Transactional
public class CustomRepository<T> implements ICustomRepository<T> {
private final String tableName;
private final RowMapper<T> rowMapper;
private final JdbcTemplate jdbcTemplate;
@Override
public List<T> findAll() {
return jdbcTemplate.batchUpdate("... ", rowMapper);
}
}
// ICustomRepository.java
public interface ICustomRepository<T> {
List<T> findAll();
}
Is it enough to put @Transactional
just in the base class so that the call findAll()
from sublasses also become transactional. Or it is better to place @Transactional
on subclasses and not put it on base class?
Solution
I have investigated it.
As @Transactional
is an inhereted annotation then if we mark a base class by @Transactional
then all its subclasses will be also @Transactional
automatically.
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
...
}
The inhereted annotation documentation:
Indicates that an annotation type is automatically inherited. If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type. This process will be repeated until an annotation for this type is found, or the top of the class hierarchy (Object) is reached. If no superclass has an annotation for this type, then the query will indicate that the class in question has no such annotation. Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class.
Note also that this meta-annotation only causes annotations to be inherited from superclasses; annotations on implemented interfaces have no effect.
Answered By - Mikhail Geyer
Answer Checked By - David Marino (JavaFixing Volunteer)