Core Class: JdbcTemplate
update() – for INSERT, UPDATE, DELETE
query() – for SELECT returning multiple rows
queryForObject() – for SELECT returning a single row or value
batchUpdate() – for batch operations
@Autowired
private JdbcTemplate jdbcTemplate;
// Insert data
public void addEmployee(Employee emp) {
String sql = "INSERT INTO employees (id, name, salary) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, emp.getId(), emp.getName(), emp.getSalary());
}
// Query data
public Employee getEmployeeById(int id) {
String sql = "SELECT * FROM employees WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Employee.class), id);
}
Employee Class:
public class Employee {
private int id;
private String name;
private double salary;
// Getters and Setters
}
It maps column names from the database to Java bean property names.
String sql = "SELECT * FROM employees WHERE id = ?";
Employee emp = jdbcTemplate.queryForObject(
sql,
new BeanPropertyRowMapper<>(Employee.class), // maps columns to Employee fields
id
);
BeanPropertyRowMapper automatically populates the Employee object.
A transaction is a logical unit of work that either completes fully or fails entirely — following the ACID principles:
Atomicity – all or nothing
Consistency – data must remain valid
Isolation – transactions don’t interfere with each other
Durability – once committed, changes persist
Explicitly managing transactions in the code using the PlatformTransactionManager or TransactionTemplate.
Example:
@Autowired
private PlatformTransactionManager transactionManager;
public void transferMoney() {
TransactionTemplate template = new TransactionTemplate(transactionManager);
template.execute(status -> {
try {
accountRepository.debit("A", 100);
accountRepository.credit("B", 100);
} catch (Exception e) {
status.setRollbackOnly(); // optional: mark for rollback
}
return null;
});
}
TransactionTemplate.execute() — begins the transaction and commits it when sucessful.
Setting status.setRollbackOnly() → Spring marks the transaction as rollback-only — meaning it will roll back even if no exception bubbles up.
PlatformTransactionManager: Core interface that defines transaction management operations such as begin, commit, and rollback.
Implementations include:
DataSourceTransactionManager (for JDBC)
JpaTransactionManager (for JPA)
HibernateTransactionManager (for Hibernate)
JtaTransactionManager (for distributed transactions)
Declare transactional boundaries using the @Transactional annotation.
Example: Method level
@Service
public class BankService {
@Transactional // Method level is safe and preferred
public void transferMoney(String from, String to, double amount) {
accountRepository.debit(from, amount);
accountRepository.credit(to, amount);
}
}
Example: Class level
@Service
@Transactional // Applies to all public methods in the class
public class BankService {
public void transferMoney(String from, String to, double amount) {
accountRepository.debit(from, amount);
accountRepository.credit(to, amount);
}
}
Spring automatically creates a proxy that begins and commits (or rolls back) a transaction around this method.
@Transactional Annotation = Marks a method or class as transactional.
Configuration includes:
propagation – how transactions relate to each other
isolation – how data access is isolated between transactions
timeout – how long a transaction can run
readOnly – for optimization when no data modifications occur
rollbackFor / noRollbackFor – which exceptions trigger rollback
Example:
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
rollbackFor = Exception.class
)
Defines how transactions interact when one transactional method calls another.
REQUIRED: Join existing transaction or start a new one if none exists (default).
REQUIRES_NEW: Always start a new transaction; suspend existing ones.
SUPPORTS: Join existing transaction if available; otherwise run non-transactionally.
MANDATORY: Must run inside an existing transaction; throws exception otherwise.
NEVER: Must run outside of a transaction.
NESTED: Execute within a nested transaction (if supported).
Control how transaction integrity is maintained in concurrent environments:
READ_UNCOMMITTED: May read uncommitted changes (dirty reads). [Prevents: Nothing]
READ_COMMITTED: Only reads committed data. [Prevents: Dirty reads]
REPEATABLE_READ: Ensures consistent reads of same data. [Prevents: Dirty + non-repeatable reads]
SERIALIZABLE: Highest isolation, but slowest performance. [Prevents: All anomalies]
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
@Configuration → Marks this class as a Spring configuration class (like a replacement for XML config).
@EnableTransactionManagement → Tells Spring to look for @Transactional annotations in your beans and to create transactional proxies around them.
The transactionManager() bean: → Registers a JpaTransactionManager in the Spring context so that Spring knows how to handle transactions for JPA.