1. Transaction Stretegy
- Spring이 트랜잭션을 어떻게 처리할지 정의
- TransactionManager 인터페이스에서 담당
2. TrasactionDefinition
- 트랜잭션의 동작 방식 정의
더보기
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1; // 데이터베이스 기본 격리 수준 사용
int ISOLATION_READ_UNCOMMITTED = 1; // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = 2; // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = 4; // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = 8; // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;
int TIMEOUT_DEFAULT = -1;
default int getPropagationBehavior() { return PROPAGATION_REQUIRED; }
default int getIsolationLevel() { return ISOLATION_DEFAULT; }
default int getTimeout() { return TIMEOUT_DEFAULT; }
default boolean isReadOnly() { return false; }
@Nullable
default String getName() { return null; }
static TransactionDefinition withDefaults() { return StaticTransactionDefinition.INSTANCE; }
}
Propagation
- 트랜잭션이 다른 트랜잭션 컨텍스트 내에서 어떻게 동작해야 하는지 설정하는 방법
REQUIRED
- 외부 트랜잭션 O: join
- 외부 트랜잭션 X: 새 트랜잭션 시작
SUPPORTS
- 외부 트랜잭션 O: join
- 외부 트랜잭션 X: 트랜잭션 없이 실행
MANDATORY
- 외부 트랜잭션 O: join
- 외부 트랜잭션 X: 예외 발생 (IllegalTransactionStateException)
REQUIRES_NEW
- 외부 트랜잭션 O: 새 트랜잭션 시작 (외부 트랜잭션 일시 정지)
- 외부 트랜잭션 X: 새 트랜잭션 시작
NOT_SUPPORTED
- 외부 트랜잭션 O: 트랜잭션 없이 실행 (외부 트랜잭션 일시 정지)
- 외부 트랜잭션 X: 트랜잭션 없이 실행
NEVER
- 외부 트랜잭션 O: 예외 발생 (IllegalTransactionStateException)
- 외부 트랜잭션 X: 새 트랜잭션 시작
NESTED
- 외부 트랜잭션 O: 중첩 트랜잭션 시작 (부모 트랜잭션에 중첩 트랜잭션의 Savepoint 생성됨)
- 부모 트랜잭션 예외 시: 중첩 트랜잭션 모두 롤백됨
- 중첩 트랜잭션 예외 시: 중첩 트랜잭션 Savepoint까지 수행됨 (부모 트랜잭션 계속 동작)
- 외부 트랜잭션 X: 새 트랜잭션 시작
Isolation
- 트랜잭션이 다른 트랜잭션으로 얼마나 독립적으로 동작하는지 정의
- 레벨이 높아질수록 데이터 무결성은 높아지지만, 성능상 비용이 많이 듬
READ_UNCOMMITTED
- 트랜잭션이 커밋하지 않은 데이터도 읽을 수 있음
- 문제점: Dirty Read, Non-repeatable Read, Phantom Read
READ_COMMITTED
- 트랜잭션이 커밋된 데이터만 읽을 수 있음
- 문제점: Non-repeatable Read, Phantom Read
REPEATABLE_READ
- 읽기 잠금: 트랜잭션이 읽고 있는 자원을 다른 트랜잭션에서 수정 및 삭제 불가
- 문제점: Phantom Read
Serializable
- 읽기 잠금: 트랜잭션이 읽고 있는 자원을 다른 트랜잭션에서 수정 및 삭제 불가
- 쓰기 잠금: 트랜잭션이 수정하거나 삭제하려는 자원을 다른 트랜잭션에서 읽기, 수정 및 삭제 불가
- 문제점: 성능
Timeout
- 트랜잭션이 얼마나 오래 실행될 수 있는지 설정
Read-only
- 트랜잭션이 데이터 읽기만 할지 여부 결정
3. TrasactionStatus
트랜잭션 상태
- isNewTransaction(): 새로 생성된 트랜잭션 여부 (새로 시작된 것인지, 외부 트랜잭션에 참여한 것인지)
- isRollbackOnly(): 롤백 전용 여부
- isCompleted(): 완료 여부
트랜잭션 동작
- flush(): 모든 쓰기 작업을 db에 강제로 반영
트랜잭션 설정
- setRollbackOnly(): 현재 트랜잭션을 롤백 전용으로 설정 (커밋 X, 반드시 롤백 전용으로 설정)
더보기
@Service
public class ExampleService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private JdbcTemplate jdbcTemplate;
public void performTransactionalOperation() {
// 트랜잭션 정의 생성
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 트랜잭션 시작
TransactionStatus status = transactionManager.getTransaction(definition);
try {
// 트랜잭션이 새로운 것인지 확인
if (status.isNewTransaction()) {
System.out.println("새로운 트랜잭션이 시작되었습니다.");
}
// 데이터베이스 작업 수행
jdbcTemplate.update("INSERT INTO my_table (column1) VALUES (?)", "Test Value");
// 플러시를 통해 쓰기 작업을 강제로 데이터베이스에 반영
status.flush();
// 비즈니스 로직에 따른 롤백 전용 설정
if (/* 어떤 조건 */) {
status.setRollbackOnly();
}
// 롤백 전용 상태인지 확인
if (status.isRollbackOnly()) {
System.out.println("트랜잭션은 롤백 전용 상태로 설정되었습니다.");
// 명시적으로 롤백
transactionManager.rollback(status);
return;
}
// 트랜잭션 커밋
transactionManager.commit(status);
System.out.println("트랜잭션이 성공적으로 커밋되었습니다.");
} catch (Exception e) {
// 예외 발생 시 트랜잭션 롤백
transactionManager.rollback(status);
System.out.println("트랜잭션이 롤백되었습니다.");
}
}
}
4. TransactionManager (PlatformTransactionManager)
- 트랜잭션 관리의 핵심 (Spring)
- 선언적으로 사용됨 (설정 및 관리)
더보기
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
Implementataion
DataSourceTransactionManager
- JDBC 기반 데이터 소스
- Local Transaction
HibernateTransactionManager
- Hibernate와 연동된 트랜잭션 관리 담당 (start, commit, rollback)
- SessionFactory와 연동
- Local Transaction
더보기
@Configuration
@EnableTransactionManagement // 트랜잭션 관리 활성화
public class AppConfig {
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
}
JtaTransactionManager
- Global Transaction
더보기
@Bean
public JtaTransactionManager transactionManager() {
return new JtaTransactionManager();
}
장점
추상화
- 기술, 트랜잭션 종류와 상관없이 코드 작성이 동일
비침투적
5. Hibernate
LocalSessionFactoryBean
- SessionFactory 설정 및 초기화
- Spring 컨테이너에 의해 트랜잭션을 관리할 수 있음 (PlatformTransactionManager와 통합됨)
더보기
@Configuration
@EnableTransactionManagement
public class HibernateConfig {
@Autowired
private DataSource dataSource; // DataSource는 DB 연결을 관리
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setPackagesToScan("com.example.myapp.entity"); // 엔티티 클래스가 있는 패키지 설정
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public PlatformTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.format_sql", "true");
properties.put("hibernate.hbm2ddl.auto", "update");
return properties;
}
}
6. JPA
LocalContainerEntityManagerFactoryBean
- JPA의 EntityManagerFactory 설정
- Hibernate와 JPA의 설정이 통합됨
더보기
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.myapp.entity"); // JPA 엔티티 클래스 패키지 스캔
// Hibernate JPA 공급자 설정
em.setJpaVendorAdapter(new org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter());
return em;
}
7. DataSource
- 데이터베이스 연결 관리
출처