스프링DB 15

초기화 시점에 트랜잭션적용

@PostConstruct를 사용해서 빈이 초기화 된 후에 실행하고 싶은 초기화 메서드에 트랜잭션을 적용하고 싶다. @PostConstruct @Transactional public void initV1() { boolean isActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("Hello init @PostConstruct tx active={}", isActive); } 하지만 이건 트랜잭션이 적용되지 않는다. 이유는 @PostConstruct가 먼저 실행되고 @Transactional이 실행되어서 초기화 코드에는 @Transactional이 적용되지 않기 때문이다. 순서가 맞지 않아서 적용이 안되는것. 해..

스프링DB 2023.06.01

스프링 트랜잭션 내부 호출시 발생하는 문제

스프링 트랜잭션을 사용하면 즉 @Transactional을 사용하면 AOP가 적용되어서 프록시 방식으로 AOP를 사용한다. 프록시 객체가 요청을 먼저 받아서 트랜잭션을 처리하고, 실제 객체를 호출해준다. 그렇기 때문에 트랜잭션을 적용하려면 항상 프록시를 통해 비즈니스 로직을 수행해야한다. (프록시를 통해서 대상 객체(Target) 호출) 이렇게 해야 프록시에 먼저 트랜잭션을 적용하고 이후에 대상 객체를 호출하게 되는데 만약 프록시를 거치지 않고 대상 객체를 직접 호출 하게 되면 AOP가 적용되지 않고, 트랜잭션도 적용되지 않게 된다. 코드로 상황을 보면 이렇다. @Slf4j static class CallService { public void external() { log.info("call extern..

스프링DB 2023.06.01

트랜잭션 전파

이번 글은 서로 연결돼있는 코드에서 트랜잭션이 두번 발생했을때 어떻게 되느냐 인데 @Test void double_commit_rollback() { log.info("트랜잭션1 시작"); final TransactionStatus tx1 = txManager.getTransaction(new DefaultTransactionDefinition()); log.info("트랜잭션1 커밋"); txManager.commit(tx1); log.info("트랜잭션2 시작"); final TransactionStatus tx2 = txManager.getTransaction(new DefaultTransactionDefinition()); log.info("트랜잭션2 롤백"); txManager.rollback(..

스프링DB 2022.09.16

트랜잭션 이해

위 사진을 올린건 트랜잭션을 사용하기위해선 트랜잭션 매니저가 필요한데 DataSourceTransactionManager를 주입 받으면 만약 JpaTransactionManager나 다른 TransactionManager로 갈아끼우게 될때 코드를 수정해야한다. 하지만 스프링에서 제공하는 PlatformTransactionManager를 사용하면 다른 TransactionManager로 바뀌어도 코드를 수정하지 않아도 된다. OCP를 지킬수 있다. 그러면 어떻게 PlatformTransactionManager를 사용할 수 있을까? 선언적 트랜잭션 관리와 프로그래밍 방식 트랜잭션 관리가 있다. 프로그래밍 방식의 트랜잭션 관리는 트랜잭션 매니저 또는 트랜잭션 템플릿 등을 사용해서 트랜잭션 관련 코드를 직접 작..

스프링DB 2022.09.15

트랜잭션 AOP 주의 사항

첫번째는 @Transactional을 쓸경우 public 이 붙은 메소드에서만 적용이된다. 만약 protected나 pakage visible일 경우에는 @Transactional이 작동하지 않는다. //Transaction 작동함 @Transactional public void internal() { log.info("call internal"); printTxInfo(); } //Transaction 작동안함 @Transactional void internal() { log.info("call internal"); printTxInfo(); } private void printTxInfo() { final boolean txActive = TransactionSynchronizationManager...

스프링DB 2022.09.14

트랜잭션 매니저 선택

만약 JPA를 쓴다면 JPA, 스프링 데이터 JPA, Querydsl은 모두 JPA기술을 사용하는 거라 트랜잭션 매니저로 JpatransactionManager를 선택하면 되는데 해당 기술을 사용하면 스프링 부트는 자동으로 JpatransactionManager를 스프링 빈으로 등록한다. 그런데 만약 아주 복잡한 통계쿼리를 자주 사용해야하면 JdbcTemplate이나 Mabatis를 사용해야하는데 얘네들은 DataSourceTransactionManager를 사용한다. 이렇게 두 기술을 함께 사용할 경우 트랜잭션 매니저가 달라진다. 결국 트랜잭션을 하나로 묶을 수 없는 문제가 발생하는데 JpatransactionManager는 DataSourceTransactionManager가 제공하는 기능도 대부분 ..

스프링DB 2022.09.14

JPQL

JPA는 JPQL(Java Persistence Query Language)이라는 객체지향 쿼리 언어를 제공한다. 주로 여러 데이터를 복잡한 조건으로 조회할때 사용한다. SQL이 테이블을 대상으로 한다면 JPQL은 엔티티 객체를 대상으로 SQL을 실행한다. String jpql = "select i from Item i"; // Item이라는 객체 별칭을 i로 하고 select절에 i를 넣어서 Item 객체에 있는 모든 필드들을 조회하는 쿼리 그래서 위와 같이 from 다음에 Item 엔티티 객체 이름이 들어간다. 자바 객체처럼 대소문자를 가리기 때문에 구분 해야한다. 결과적으로 JPQL을 실행하면 그 안에 포함된 엔티티 객체의 매핑 정보를 활용해서 SQL을 만들게 된다. 예시) 실행된 JPQL sele..

스프링DB 2022.09.01

Jpa 적용

@Data // 연습용이라 씀 @Entity // @Table(name = "item") // table명과 객체명이 같으면 안적어줘도 된다. public class Item { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "item_name", length = 10) // 컬럼명과 객체 필드명이 다른것만 작성해주면 된다. // 하지만 지금처럼 스프링부트와 통합해서 사용하면 필드 이름을 컴럼명으로 변경할때 객체 필드의 카멜 케이스를 테이블 컬럼의 언더스코어로 자동 변환해주어서 생략해도 된다. private String itemName; private Integer price; private I..

스프링DB 2022.09.01