Notice
Recent Posts
Link
Tags
- 데이터베이스
- mysql
- join
- Docker
- spring boot
- sql
- spring security 6
- 스프링부트
- Django
- spring mvc
- 스프링
- select
- ORM
- session
- SSL
- AWS
- DI
- jpa
- 문자열
- spring
- 프로그래머스
- 1차원 배열
- nginx
- @transactional
- PYTHON
- Git
- string
- springboot
- 자바
- java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Archives
개발하는 자몽
[JPA Error] No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call 본문
Java/Spring
[JPA Error] No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call
jaamong 2024. 10. 23. 20:04에러 원인
정말... 바보같은... 실수였다...
오류가 났던 테스트 코드는 아래와 같다.
...
@PersistenceContext
EntityManager em;
@Test
void test() {
UserEntity userEntity = UserEntity.builder()
.nickname("test")
.email("test@example.com")
.build();
userEntity = userRepository.save(userEntity);
userService.sumTotalAmount(userEntity, 10_000L);
Long requestAmount = 5_000L;
Long updatedAmount = userService.minusTotalAmount(userEntity, requestAmount);
em.flush();
em.clear();
//잘 반영이 되었는지 확인하기 위해 영속성 컨텍스트를 비우고 새로 조회
UserEntity findEntity = userRepository.findById(userEntity.getId()).get();
assertThat(updatedAmount).isEqualTo(5_000L);
assertThat(findEntity.getTotalAmount()).isEqualTo(updatedAmount);
}
테스트 하고 싶었던 부분은 `minusTotalAmount`가 요청한 만큼 `totalAmount`를 잘 감소시키는 지였다.
우선 `em.flush()`로 쿼리를 날려주고, 영속성 컨텍스트를 비운 상태에서 객체를 새로 조회하기 위해 `em.clear()`를 호출했었다. 그다음 객체를 새로 조회하여 필드에 제대로 값이 반영이 되었는지 검증했다.
그리고 제목과 같은 에러가 발생했다.
번역하자면...
현재 스레드에 사용 가능한 실제 트랜잭션이 있는 EntityManager가 없습니다. 'flush' 호출을 안정적으로 처리할 수 없습니다.
`EntityManager`가 `flush()`를 호출했는데 이를 처리할 Transaction이 없어서 실행할 수 없다는 뜻이다.
JPA는 트랜잭션 단위로 기능을 수행하고, 수행하면서 1차 캐시에 저장된 엔티티들은 DB에 flush되어 영속화된다. 그런데 위 테스트 코드는 트랜잭션이 없기 때문에 위와 같은 에러가 발생했던 것이다.
에러 해결
아주 간단히 해결할 수 있다... 테스트할 메서드나 클래스에 `@Transactional`를 붙여주면 된다!
...
@PersistenceContext
EntityManager em;
@Test
@Transactional
void test() {
UserEntity userEntity = UserEntity.builder()
.nickname("test")
.email("test@example.com")
.build();
userEntity = userRepository.save(userEntity);
userService.sumTotalAmount(userEntity, 10_000L);
Long requestAmount = 5_000L;
Long updatedAmount = userService.minusTotalAmount(userEntity, requestAmount);
em.flush();
em.clear();
//잘 반영이 되었는지 확인하기 위해 영속성 컨텍스트를 비우고 새로 조회
UserEntity findEntity = userRepository.findById(userEntity.getId()).get();
assertThat(updatedAmount).isEqualTo(5_000L);
assertThat(findEntity.getTotalAmount()).isEqualTo(updatedAmount);
}
이제 `flush()`를 호출하고 콘솔창을 확인하면 쿼리가 제대로 나가는 것을 확인할 수 있다^^!
'Java > Spring' 카테고리의 다른 글
[JPA] 임베디드 타입(@Embeddable, @Embedded)에 관하여 (0) | 2024.08.23 |
---|---|
[Spring Boot / Error] Required request body is missing (0) | 2024.07.13 |
[Spring Security] 예외 처리하기 (0) | 2024.06.21 |
[Spring Security] 역할/권한 구현하기 (0) | 2024.06.14 |
[Spring Security] 토큰 기반 로그인/로그아웃 구현하기 (0) | 2024.06.08 |
Comments