Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- JPA
- useEffect
- Git
- NCP
- nginx
- dbeaver
- wildfly
- springboot
- database
- gson
- nodejs
- gradle
- mybatis
- Spring
- kubectl
- docker
- jetbrains
- Windows
- IntelliJ
- Kubernetes
- JavaScript
- VSCode
- intellijIDEA
- react
- log4j2
- MySQL
- Java
- tibero
- BPMN
- LOG4J
Archives
- Today
- Total
두 손끝의 창조자
Domain과 Web프로젝트 분리시 트랜잭션 문제 본문
소스 코드
- domain project
- 소스코드
package cothe.service; import cothe.entity.Yo; import javax.transaction.Transactional; public class YoService { private final YoRepository yoRepository; public YoService(YoRepository yoRepository) { this.yoRepository = yoRepository; } @Transactional public void updateName(Long id, String name) { Yo yo = yoRepository.findById(id).get(); yo.updateName(name); } @Transactional public void addYo(String name) { Yo yo = new Yo(name); yoRepository.save(yo); } }
package cothe.service; import cothe.entity.Yo; import java.util.Optional; public interface YoRepository { Optional<Yo> findById(Long id); Yo save(Yo yo); }
package cothe.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Yo { @Id @GeneratedValue private Long id; private String name; protected Yo() { } public void updateName(String name) { this.name = name; } public Yo(String name) { this.name = name; } }
- 의존성 설정
dependencies { api group: 'jakarta.persistence', name: 'jakarta.persistence-api', version: '2.2.3' api group: 'jakarta.transaction', name: 'jakarta.transaction-api', version: '1.3.3' }
- 소스코드
- Entity와 Transaction을 표현할 수 있는 최소한의 의존성을 가지고 도메인 코드를 작성
- web project
- 소스코드
package cothe.repository.repository; import cothe.entity.Yo; import cothe.service.YoRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public class JpaYoRepository implements YoRepository { private final SpringJpaYoRepository springJpaYoRepository; public JpaYoRepository(SpringJpaYoRepository springJpaYoRepository) { this.springJpaYoRepository = springJpaYoRepository; } @Override public Optional<Yo> findById(Long id) { return springJpaYoRepository.findById(id); } @Override public Yo save(Yo yo) { return springJpaYoRepository.save(yo); } }
package cothe.repository.repository; import cothe.entity.Yo; import org.springframework.data.jpa.repository.JpaRepository; public interface SpringJpaYoRepository extends JpaRepository<Yo, Long> { }
package cothe.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cothe.service.YoRepository; import cothe.service.YoService; @RestController public class WebRestController { private final YoRepository jpaYoRepository; public WebRestController(YoRepository yoRepository) { this.jpaYoRepository = yoRepository; } @RequestMapping("/update") public void updateName(Long id, String name) { YoService yoService = new YoService(jpaYoRepository); yoService.updateName(id, name); } @RequestMapping("/add") public void addYo(String name) { YoService yoService = new YoService(jpaYoRepository); yoService.addYo(name); } }
- 의존성 설정
dependencies { implementation project(":domain-jakarta") implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' runtimeOnly 'mysql:mysql-connector-java' }
- 소스코드
- Spring-Boot 2.4.0 를 이용하여 간단하게 웹 서비스 구현
테스트 요청
- localhost:8080/add?name=hahaha
- localhost:8080/update?id=1&name=kkkkk
실행 결과
insert
into
yo
(name, id)
values
(?, ?)
select
yo0_.id as id1_0_0_,
yo0_.name as name2_0_0_
from
yo yo0_
where
yo0_.id=?
insert 쿼리는 수행되었지만 update는 수행되지 않았음
추가 실험
domain 프로젝트에 api group: 'org.springframework.data', name: 'spring-data-jpa', version: '2.4.1'
추가
cothe.service.YoService
의 @Transactional
를 org.springframework.transaction.annotation.Transactional
로 변경
실행 결과
똑같은 결과 나옴
추가 실행
cothe.service
패키지를 web project로 옮김
실행 결과
똑같은 결과 나옴
추가 실행
cothe.service.YoService
를 @Service
애노테이션을 이용해 빈으로 등록
실행 결과
정상 수행됨
결론
@Transactional
은 Spring Container에 속해 있는 빈일 때만 동작한다.
최종 소스
- domain project
- 소스코드
package cothe.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Yo { @Id @GeneratedValue private Long id; private String name; protected Yo() { } public void updateName(String name) { this.name = name; } public Yo(String name) { this.name = name; } }
- 의존성 설정
dependencies { api group: 'jakarta.persistence', name: 'jakarta.persistence-api', version: '2.2.3' }
- Entity와 Transaction을 표현할 수 있는 최소한의 의존성을 가지고 도메인 코드를 작성
- web project
- 소스코드
package cothe.repository.repository; import cothe.entity.Yo; import cothe.service.YoRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public class JpaYoRepository implements YoRepository { private final SpringJpaYoRepository springJpaYoRepository; public JpaYoRepository(SpringJpaYoRepository springJpaYoRepository) { this.springJpaYoRepository = springJpaYoRepository; } @Override public Optional<Yo> findById(Long id) { return springJpaYoRepository.findById(id); } @Override public Yo save(Yo yo) { return springJpaYoRepository.save(yo); } }
package cothe.service; import cothe.entity.Yo; import java.util.Optional; public interface YoRepository { Optional<Yo> findById(Long id); Yo save(Yo yo); }
package cothe.service; import cothe.entity.Yo; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class YoService { private final YoRepository yoRepository; public YoService(YoRepository yoRepository) { this.yoRepository = yoRepository; } @Transactional public void updateName(Long id, String name) { Yo yo = yoRepository.findById(id).get(); yo.updateName(name); } @Transactional public void addYo(String name) { Yo yo = new Yo(name); yoRepository.save(yo); } }
package cothe.repository.repository; import cothe.entity.Yo; import org.springframework.data.jpa.repository.JpaRepository; public interface SpringJpaYoRepository extends JpaRepository<Yo, Long> { }
package cothe.controller; import cothe.service.YoService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class WebRestController { private final YoService yoService; public WebRestController(YoService yoService) { this.yoService = yoService; } @RequestMapping("/update") public void updateName(Long id, String name) { yoService.updateName(id, name); } @RequestMapping("/add") public void addYo(String name) { yoService.addYo(name); } }
- 의존성 설정
dependencies { implementation project(":domain-jakarta") implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' runtimeOnly 'mysql:mysql-connector-java' }
- 소스코드
- Spring-Boot 2.4.0 를 이용하여 간단하게 웹 서비스 구현
반응형
Comments