분류 전체보기 1341

Ch10. 스프링 트랜잭션 전파(기본) - 스프링 트랜잭션 전파(커밋, 롤백)

트랜잭션이 둘 이상 있을 때 어떻게 동작하는지 자세히 알아보고, 스프링이 제공하는 트랜잭션 전파 (propagation)라는 개념도 알아보자. 트랜잭션 전파를 이해하는 과정을 통해서 스프링 트랜잭션의 동작 원리도 더 깊이 있게 이해할 수 있을 것이다 @Slf4j @SpringBootTest public class BasicTxTest { @Autowired PlatformTransactionManager txManager; @TestConfiguration static class Config{ @Bean public PlatformTransactionManager transactionManager(DataSource dataSource){ return new DataSourceTransactionMana..

Ch09. 스프링 트랜잭션 이해 - 예외와 트랜잭션 커밋, 롤백

기본 예외가 발생했는데, 내부에서 예외를 처리하지 못하고, 트랜잭션 범위( @Transactional가 적용된 AOP ) 밖으로 예외를 던지면 어떻게 될까? 예외 발생 시 스프링 트랜잭션 AOP는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다. 언체크 예외인 RuntimeException , Error와 그 하위 예외가 발생하면 트랜잭션을 롤백한다. 체크 예외인 Exception 과 그 하위 예외가 발생하면 트랜잭션을 커밋한다. 물론 정상 응답(리턴)하면 트랜잭션을 커밋한다 RollbackTest @SpringBootTest public class RollbackTest { @Autowired RollbackService service; @Test public void runtimeException(..

Ch09. 스프링 트랜잭션 이해 - 트랜잭션 옵션 소개

/** * Describes a transaction attribute on an individual method or on a class. * * When this annotation is declared at the class level, it applies as a default * to all methods of the declaring class and its subclasses. Note that it does not * apply to ancestor classes up the class hierarchy; inherited methods need to be * locally redeclared in order to participate in a subclass-level annotation..

Ch09. 스프링 트랜잭션 이해 - 트랜잭션 AOP 주의 사항(초기화 시점)

@SpringBootTest public class InitTxTest { @Autowired private Hello hello; @Test public void go(){ //초기화 코드는 스프링이 초기화 시점에 호출한다. } @TestConfiguration static class InitTxTestConfig{ @Bean public Hello hello(){ return new Hello(); } } @Slf4j static class Hello{ @PostConstruct @Transactional public void initV1(){ boolean isActive = TransactionSynchronizationManager.isActualTransactionActive(); log.in..

Ch09. 스프링 트랜잭션 이해 - 트랜잭션 AOP 주의 사항(프록시 내부 호출)

문제 @Transactional을 사용하면 스프링의 트랜잭션 AOP가 적용된다. 트랜잭션 AOP는 기본적으로 프록시 방식의 AOP를 사용한다. 앞서 배운 것 처럼 @Transactional을 적용하면 프록시 객체가 요청을 먼저 받아서 트랜잭션을 처리하고, 실제 객체를 호출해준다. 따라서 트랜잭션을 적용하려면 항상 프록시를 통해서 대상 객체(Target)를 호출해야 한다. 이렇게 해야 프록시에서 먼저 트랜잭션을 적용하고, 이후에 대상 객체를 호출하게 된다. 만약 프록시를 거치지 않고 대상 객체를 직접 호출하게 되면 AOP가 적용되지 않고, 트랜잭션도 적용되지 않는다 AOP를 적용하면 스프링은 대상 객체 대신에 프록시를 스프링 빈으로 등록한다. 따라서 스프링은 의존관계 주입시에 항상 실제 객체 대신에 프록시..

Ch09. 스프링 트랜잭션 이해 - 트랜잭션 적용 위치

스프링에서 우선순위는 항상 더 구체적이고 자세한 것이 높은 우선순위를 가진다. 이것만 기억하면 스프링에서 발생하는 대부분의 우선순위를 쉽게 기억할 수 있다. 그리고 더 구체적인 것이 더 높은 우선순위를 가지는 것은 상식적으로 자연스럽다 예를 들어서 메서드와 클래스에 애노테이션을 붙일 수 있다면 더 구체적인 메서드가 더 높은 우선순위를 가진다. 인터페이스와 해당 인터페이스를 구현한 클래스에 애노테이션을 붙일 수 있다면 더 구체적인 클래스가 더 높은 우선순위를 가진다 @SpringBootTest public class TxLevelTest { @Autowired LevelService service; @Test public void orderTest() { service.write(); service.rea..

Ch09. 스프링 트랜잭션 이해 - 프로젝트 생성 & 트랜잭션 적용 확인

프로젝트 생성 dependencies { ... //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } test에서도 Lombok을 사용하기 위해 의존성 추가 트랜잭션 적용 확인 @Slf4j @SpringBootTest public class TxBasicTest { @Autowired BasicService basicService; @Test public void proxyCheck(){ log.info("aop class={}", basicService.getClass()); assertThat(AopUtils.isAopProxy(basicService)..

Ch09. 스프링 트랜잭션 이해 - 스프링 트랜잭션 소개

스프링 트랜잭션 추상화 JDBC 트랜잭션 코드 예시 public void accountTransfer(String fromId, String toId, int money) throws SQLException { Connection con = dataSource.getConnection(); try { con.setAutoCommit(false); //트랜잭션 시작 //비즈니스 로직 bizLogic(con, fromId, toId, money); con.commit(); //성공시 커밋 } catch (Exception e) { con.rollback(); //실패시 롤백 throw new IllegalStateException(e); } finally { release(con); } } JPA 트랜잭션 ..

Ch08. 활용 방안 - 다양한 데이터 접근 기술 조합

어떤 데이터 접근 기술을 선택하는 것이 좋을까? 이 부분은 하나의 정답이 있다기보다는, 비즈니스 상황과, 현재 프로젝트 구성원의 역량에 따라서 결정하는 것이 맞다 생각한다. JdbcTemplate이나 MyBatis 같은 기술들은 SQL을 직접 작성해야 하는 단점은 있지만 기술이 단순하기 때문에 SQL에 익숙한 개발자라면 금방 적응할 수 있다. JPA, 스프링 데이터 JPA, Querydsl 같은 기술들은 개발 생산성을 혁신할 수 있지만, 학습 곡선이 높기 때문에, 이런 부분을 감안해야 한다. 그리고 매우 복잡한 통계 쿼리를 주로 작성하는 경우에는 잘 맞지 않는다. 개인적으로 추천하는 방향은 JPA, 스프링 데이터 JPA, Querydsl을 기본으로 사용하고, 만약 복잡한 쿼리를 써야 하는데, 해결이 잘 ..

Ch08. 활용 방안 - 실용적인 구조

ItemRepositoryV2 는 스프링 데이터 JPA의 기능을 제공하는 리포지토리이다. ItemQueryRepositoryV2 는 Querydsl을 사용해서 복잡한 쿼리 기능을 제공하는 리포지토리이다 이렇게 둘을 분리하면 기본 CRUD와 단순 조회는 스프링 데이터 JPA가 담당하고, 복잡한 조회 쿼리는 Querydsl이 담당하게 된다. 물론 ItemService 는 기존 ItemRepository 를 사용할 수 없기 때문에 코드를 변경해야 한다 ItemRepositoryV2 public interface ItemRepositoryV2 extends JpaRepository { } ItemRepositoryV2 는 JpaRepository 를 인터페이스 상속 받아서 스프링 데이터 JPA의 기능을 제공하는..