본문 바로가기

전체 글

(197)
[Spring] @PostConstruct와 @Transactional @PostConstruct와 @Transactional이 동시에 사용되었을 때 트랜잭션이 적용되지 않는다. 그 이유는 두 애너테이션이 호출되는 시점이 다르기 때문이다. 스프링 생명 주기 스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존 관계 주입 -> 초기화 콜백 -> 사용 -> 소멸 콜백 -> 스프링 컨테이너 종료 @PostConstruct 호출 시점 스프링 빈이 생성 되고 의존 관계가 주입된 후에 호출된다. @Transactional 호출 시점 초기화 콜백 이후 컨테이너가 초기화된 후에 호출된다. 코드 Hello 클래스가 빈으로 등록되어 있고, initV1() 메서드에 @PostConstruct 애너테이션이 사용되고 있다. @SpringBootTest @Slf4j public class InitT..
[Spring] @Transactional 적용 범위 클래스에 @Transactional을 붙이면 모든 메서드에 트랜잭션이 적용된다. 특정 메서드에 @Transactional을 붙이면 해당 메서드에만 트랜잭션이 적용된다. 그런데 의문이 들었다. @Transactional이 붙지 않은 메서드를 호출할 때, 해당 클래스는 AOP 프록시가 적용되어 있는지에 대해 궁금했다. 결론부터 말하자면 AOP 프록시가 적용된 상태에서 메서드를 호출하게 된다. 물론 @Transactional이 붙지 않았기 때문에 해당 메서드는 트랜잭션이 적용되지 않는다. 트랜잭션 AOP 적용 CallService 클래스를 보면 internal 메서드에 @Transactional이 붙었다. 따라서 해당 클래스는 AOP 프록시가 적용된다. AOP 프록시가 적용된다는 의미는 프록시 객체가 트랜잭션..
[JPA] DB IDENTITY 전략일 때, 영속성 컨텍스트 JPA의 경우에 EntityManager를 통해 persist를 하면 해당 객체는 영속 상태가 된다. DB에 저장된 상태가 아닌 1차 캐시에 ID-Entity 형태로 JPA에 의해 관리가 된다. 또한 Member 엔티티를 DB에 저장하기 위한 Insert 쿼리문이 DB로 날라가지 않고 쓰기 지연 저장소에 보관된다. 아래는 Member 엔티티를 persist 하였을 때, 1차 캐시에 저장되어 JPA에 의해 관리 중인 상태이다. EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.g..
[Spring-Error] Constructor with '1' parameters is already defined 결론부터 말하자면 @RequiredArgsConstructor을 사용하면서 생성자를 추가적으로 생성하였기 때문에 발생한다. @RequiredArgsConstructor 애너테이션은 final이 붙은 변수들을 모아 생성자로 만들어준다. @Configuration @RequiredArgsConstructor public class JdbcTemplateV1Config { private final DataSource dataSource; // 생략 } dataSource에 final이 붙었기 때문에 아래와 같이 생성자를 만들어준다. public JdbcTemplateV1Config(DataSource dataSource) { this.dataSource = dataSource; } Constructor wit..
[Spring] 특정 쿼리문을 만족하는 Row가 있는지 조회하는 방법, queryForObject(), JdbcTemplate 본 글은 다크모드에 최적화되어 있습니다. 특정 쿼리문을 만족하는 row가 존재하는지 확인하기 위해서는 queryForObject() 메서드를 사용해야 합니다. 이 방법은 Jpa가 아닌 JdbcTemplate을 사용하는 경우에 해당합니다. queryForObject JdbcTemplate은 queryForObject() 메서드를 제공합니다. 오버로딩이 되어 있기 때문에 여러 개가 존재합니다. T queryForObject(String sql, Object[] args, Class requiredType) 다음 상황을 가정해 봅시다. 책을 대출하려고 할 때 사용자의 이름과 책의 이름을 입력해야 합니다. 이때 사용자 이름이 등록되어 있는지 확인하려면 다음과 같이 코드를 작성할 수 있습니다. public boo..
[Spring] JdbcTemplate과 TransactionTemplate, 그리고 @Transactional 본 글은 다크모드에 최적화되어 있습니다. 스프링에는 데이터 접근 계층(Repository)에서 사용하는 JdbcTemplate과 서비스 계층(Service)에서 사용하는 TransactionTemplated 이 존재합니다. 특별한 기능을 제공하는 것은 아니고 템플릿 콜백 패턴을 사용하여 반복되는 코드를 제거해 줍니다. JdbcTemplate JdbcTemplate은 데이터 접근 계층에서 DB에 접근할 때 반복되는 코드를 제거해 줍니다. 반복되는 코드란 아래의 목록들을 말합니다. 커넥션 조회 및 동기화 PreparedStatement 생성 및 파라미터 바인딩 쿼리 실행 ResultSet으로 결과 바인딩 예외 발생 시 스프링 예외 변환기(DataAccessException) 실행 리소스 종료 위의 목록들 중..
[Spring] 트랜잭션 매니저 구현체를 bean으로 등록해야할까? 트랜잭션의 경우 서비스 계층의 비즈니스 로직에서 수행한다. 서비스 계층의 경우 트랜잭션 매니저(PlatformTransactionManager)를 사용하고 데이터 접근 계층에서는 트랜잭션 동기화 매니저(DataSourceUtils)를 사용한다. 데이터 접근 계층은 트랜잭션 동기화 매니저가 관리하는 커넥션을 꺼내어 사용하는데, 트랜잭션 동기화 매니저에 커넥션을 저장하는 것은 서비스 계층의 트랜잭션 매니저가 수행한다. 서비스 계층 서비스 계층에서 트랜션을 실행하여 커넥션을 만들고 이 커넥션을 트랜잭션 동기화 매니저에 저장시킨다. 스프링에서 사용하는 트랜잭션 매니저는 PlatformTransactionManager이다. 트랜잭션 매니저의 구현체로는 DataSourceTransactionManager, JpaT..
[Spring] 스프링 프레임워크 동작 과정, 서블릿, 핸들러, 어댑터, 뷰리졸버 김영한 님 MVC1 강의 정리본입니다. 전체 구조 1. 핸들러 매핑 정보 클라이언트(사용자)가 웹페이지에 접속을 하면 Front Controller가 해당 요청을 받는다. 가장 먼저 사용자가 접속한 URL을 처리할 수 있는 handler(핸들러)를 찾는다. 핸들러 매핑 정보에는 URL과 handler가 매핑되어 있다. 즉 URL 별로 handler가 여러 개 존재한다. ex) localhost:8080/front-controller/v5/v4/members/new-form로 접속하면 MemberFormControllerV4 핸들러가 해당 요청 URL을 처리하기 위해 사용된다. // 핸들러 매핑 정보를 담는 Map private final Map handlerMappingMap = new HashMap()..