Spring Boot | Database Access | Using Declarative Transactions
Using Declarative Transactions
- Applying
@Transactionalto a method makes the method invocation a transaction boundary. - If a
RuntimeExceptionor subclass is thrown within the transaction boundary, the transaction is rolled back. - An
Exceptionor subclass does not trigger rollback by default. - To roll back when an
Exceptionoccurs, configure@Transactional(rollbackFor = Exception.class).
Writing the Code
src/main/java/sample/springboot/jpa/MyService.java
package sample.springboot.jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class MyService {
@Autowired
private HogeRepository repository;
public void save(String value) {
Hoge hoge = new Hoge(value);
this.repository.save(hoge);
}
public void saveAndThrowRuntimeException(String value) {
this.save(value);
throw new RuntimeException("test");
}
@Transactional
public void saveAndThrowRuntimeExceptionWithTransactional(String value) {
this.saveAndThrowRuntimeException(value);
}
@Transactional
public void saveAndThrowExceptionWithTransactional(String value) throws Exception {
this.save(value);
throw new Exception("test");
}
public void show() {
this.repository.findAll().forEach(System.out::println);
}
}
src/main/java/sample/springboot/jpa/Main.java
package sample.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import sample.springboot.jpa.MyService;
@SpringBootApplication
public class Main {
public static void main(String[] args) throws Exception {
try (ConfigurableApplicationContext ctx = SpringApplication.run(Main.class, args)) {
MyService s = ctx.getBean(MyService.class);
s.save("normal");
try {
s.saveAndThrowRuntimeException("runtime exception without @Transactional");
} catch (Exception e) {}
try {
s.saveAndThrowRuntimeExceptionWithTransactional("runtime exception with @Transactional");
} catch (Exception e) {}
try {
s.saveAndThrowExceptionWithTransactional("exception with @Transactional");
} catch (Exception e) {}
s.show();
}
}
}
Result
Hoge [id=1, value=normal]
Hoge [id=2, value=runtime exception without @Transactional]
Hoge [id=4, value=exception with @Transactional]