@Transactional annotation in Spring

Sanjay Singh
3 min readMay 12, 2021

@Transactional — class level and Method level both We are now ready to use @Transactional annotation either at the class or method level.

if you are using JDBC then it will work on DAO layer, but if you are working on JPA or Spring Data then it works on service layer.
Service layer (Manager) represents your business logic and hence it should be annotated with @Transactional.

Spring provides support for both programmatic and declarative transactions .
1 Programmatic Transactions
With programmatic transactions, transaction management code needs to be explicitly written so as to commit when everything is successful and rolling back if anything goes wrong. The transaction management code is tightly bound to the business logic in this case.

2 Declarative Transactions
Declarative transactions separates transaction management code from the business logic. Spring supports declarative transactions using transaction advice (using AOP) via XML configuration in the spring context or with @Transactional annotation.

Implementation of Transactions
To start using @Transactional annotation in a Spring based application, we need to first enable annotations in our Spring application by adding the needed

<tx:annotation-driven transaction-manager=”txManager”/>
Next is to define the transaction manager bean, with the same name as specified in the above transaction-manager attribute value.
The transaction managers could be –
DataSource Transaction manager
<bean id=”txManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionManager><property name=”dataSource” ref= “datasource” /></bean>

Hibernate Transaction manager
<bean id=”txManager”
class=”org.springframework.orm.hibernate3.HibernateTransactionManager”>
<property name=”sessionFactory” ref= “sessionFactory” />
</bean>

JPA Transaction manager
<bean id=”txManager”
class=”org.springframework.orm.jpa.JpaTransactionManager”>
<property name=”entityManagerFactory” ref=”entityManagerFactory” />
</bean>
We are now ready to use @Transactional annotation either at the class or method level.

Here’s the list of Propagation values with my comments:
MANDATORY-Support a current transaction, throw an exception if none exists.
NESTED-Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else.
NEVER-Execute non-transactionally, throw an exception if a transaction exists.
NOT_SUPPORTED-Execute non-transactionally, suspend the current transaction if one exists.Does not start a transaction. Suspends any existing transaction.
REQUIRED-Support a current transaction, create a new one if none exists.
REQUIRES_NEW-Create a new transaction, suspend the current transaction if one exists.
SUPPORTS-Support a current transaction,execute non-transactionally if none exists.

@Transactional(value = “myTransactionManager”, propagation = Propagation.REQUIRED, readOnly = true)
public void myMethod() {

}

Spring Configuration Classes
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(“com.jpaapps.spring.repository”)
@PropertySource(“classpath:database.properties”)
public class DataConfig {
private final String PROPERTY_DRIVER = “driver”;
private final String PROPERTY_URL = “url”;
private final String PROPERTY_USERNAME = “user”;
private final String PROPERTY_PASSWORD = “password”;
private final String PROPERTY_SHOW_SQL = “hibernate.show_sql”;
private final String PROPERTY_DIALECT = “hibernate.dialect”;

@Autowired
Environment environment;

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
lfb.setDataSource(dataSource());
lfb.setPersistenceProviderClass(HibernatePersistence.class);
lfb.setPackagesToScan(“com.journaldev.spring.model”);
lfb.setJpaProperties(hibernateProps());
return lfb;
}

@Bean
DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUrl(environment.getProperty(PROPERTY_URL));
ds.setUsername(environment.getProperty(PROPERTY_USERNAME));
ds.setPassword(environment.getProperty(PROPERTY_PASSWORD));
ds.setDriverClassName(environment.getProperty(PROPERTY_DRIVER));
return ds;
}

Properties hibernateProps() {
Properties properties = new Properties();
properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
return properties;
}

@Bean
JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
@Configuration: this spring annotation says that it is configuration class.
@EnableTransactionManagement: this annotation allows users to use transaction management in application.
@EnableJpaRepositories(“com.journaldev.spring.repository”): indicates where the repositories classes are present.
@PropertySource(“classpath:database.properties”): says that we have property file in our classpath.

====
@Transactional annotation indicates that the method will be executed in the transaction. Spring will take care of transaction management.

@Service
public class PersonService {

@Autowired
PersonRepository<Person> personRepository;

@Transactional
public List<Person> getAllPersons() {
return (List<Person>) personRepository.findAll();
}

@Transactional
public List<Person> findByName(String name) {
return personRepository.findByFirstName(name);
}

--

--

Sanjay Singh

Java||Spring-Boot|| Micro services Application developer|| INDIA