@EventListener(ApplicationReadyEvent.class) AOP를 포함한 스프링 컨테이너가 완전히 초기화를 다 끝내고, 실행 준비가 되었을 때 발생하는 이벤트이다. 스프링이 이 시점에 해당 어노테이션이 붙은 initData() 메서드를 호출한다.(
@SpringBootTest@SpringbootApplication을 찾아 설정으로 사용한다.테스트 코드는 각각의 테스트가 독립적으로 수행되어야 하고 순서에 의해 결과가 달라지면 안된다.
H2 DB는 자바로 개발되어 있고, JVM 안에 메모리 모드로 동작하는 특별한 기능어플리케이션을 실행할 떄 H2DB 도 해당 JVM 메모리에 포함해 함께 실행한다. DB를 앱에 내장해 함께 실행한다고 해서 임베디드 모드라고 불린다.\-> 앱에서 자바 메모리를 함께 사용
스프링이 DI 컨테이너를 포함한 애플리케이션 전반의 다양한 기능을 제공한다면 JPA는 ORM 데이터 접근 기술을 제공한다.
JPA는 public 또는 protected의 기본 생성자가 필수이다. (JPA가 프록시 기술을 사용하기 위해)JPA를 설정하려면 EntityManagerFacotry, Jpa 트랜잭션 매니저 등 다양한 설정을 해야하지만 스프링 부트는 이 과정을 모두 자동화 해준다.
EntityManager는 순수한 JPA 기술이고 스프링과 관계가 없다. 따라서 엔티티 매니저는 예외가 발생하면 JPA 관련 예외를 발생시킨다.
Spring 과 JPA 사이에 Spring Data JPA가 등장했다.Spring Data는 반복적이고 자주 사용되는 로직을 대신 제공해주는 기술이다. 그 중 Spring Data Jpa 는 Jpa에 더 특화된 기술이다.
기존의 JPA 방식대로라면 jpql은 string으로 짜다보니 런타임 에러가 발생 할 수 있다.JPA,MongoDB,SQL 같은 기술들을 위해 type-safe SQL을 만드는 프레임워크이다.
기존의 구조는 위와 같았다. ItemRepository 인터페이스를 사용하기 때문에 억지로 JpaRepository를 상속받는 자식을 필드에 넣어 사용했다.구조적으로 안정되어 있는 상태이나 복잡한 상황이다.
Jpa, Jpa 스프링데이터, QueryDsl을 기본으로 사용하고, 만약 복잡한 쿼리를 써야하거나, 해결이 잘 안되는 쿼리의 경우 JdbcTemplate, MyBatis를 함께 사용하는 것이 좋다.
스프링 트랜잭션 추상화 JDBC 기술과 JPA 기술은 트랜잭션을 사용하는 코드 자체가 다르다. 기술을 변경할 때 많은 수정이 일어나게 되므로 스프링은 PlatformTransactionMangaer 라는 인터페이스로 추상화를 제공한다.
TransactionSynchronizationManager.isActualTransactionActive()위 코드는 현재 로직에 트랜잭션이 걸린 상태인지 확인하며, 트랜잭션 동기화 매니저에서 관련 작업을 했는지를 확인한다.
AOP를 적용하면 스프링은 프록시가 스프링 빈으로 등록이 되기 때문에 의존 관계 주입 시에 항상 실제 객체 대신에 프록시 객체를 주입힌다. 그렇기 때문에 일반적으로 대상 객체를 직접 호출하는 문제는 발생하지 않는다.
Hello 빈이 생성된 후에 트랜잭션을 사용한 로직을 수행하려고 하는 상황이다.
value, transactionManager스프링 빈에 등록된 어떤 트랜잭션 매니저를 사용할지 선택하기 위한 옵션이다.(직접 트랜잭션을 사용할 때 트랜잭션 매니저를 주입 받아서 사용했던 것처럼)만약 생략하면 기본으로 등록된 트랜잭션 매니저를 사용하는데 사용하는 트랜잭
예외 발생시 스프링 트랜잭션 AOP는 예외의 종류에 따라 트랜잭션을 커밋하거나 롤백한다.기존의 트랜잭션 인터셉터는 롤백하거나 커밋해서 트랜잭션이 끝나면 Completion을 출력해준다.그렇기 때문에 롤백과 커밋을 구분해주는 로그가 필요하다.
트랜잭션을 사용 중인데 그 안에서도 트랜잭션을 사용하는 경우둘 이상의 트랜잭션이 만나는 경우 어떻게 동작할까트랜잭션 매니저는 dataSourceTransactionManager를 사용하기 때문에 다음 설정으로 로그를 남긴다.logging.level.org.springf
하나의 트랜잭션이 수행중이고, 아직 끝나지 않았는데 또 다른 트랜잭션이 수행되는 경우가 있다. 먼저 시작한 트랜잭션을 외부 트랜잭션, 그 뒤의 트랜잭션을 내부 트랜잭션이라고 한다.스프링은 이 경우 하나의 트랜잭션을 만들어준다.
트랜잭션 매니저는 동작 시점에 신규 트랜잭션 여부에 따라 동작한다.논리 트랜잭션 하나라도 롤백이 발생하면 전체 트랜잭션이 롤백된다.내부 트랜잭션은 앞서 배운대로 직접 물리 트랜잭션에 관여하지 않는다.
트랜잭션의 REQUIRES_NEW 옵션을 사용한다.별도의 물리 트랜잭션을 가진다는 뜻은 DB 커넥션을 따로 사용한다는 뜻이다.Transaction 전파 수준을 Requires_new 로 설정하면 내부 트랜잭션 시작시 새로운 커넥션을 얻어 사용한다.
다음과 같은 상황이 있다고 가정하자. 클라이언트A는 MemberService 부터 트랜잭션을 물고 하나의 커넥션으로 통째로 수행하는 작업을 원하고,클라이언트B는 MemberRepository만의 독립적인 커넥션을 원할 때 어떻게 해결해야 될까?