org.hibernate.LazyInitializationException: could not initialize proxy [Bulletin.Board.domain.posts.User#38] - no Session
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FK8KCUM44FVPUPYW6F5BACCX25C: PUBLIC.COMMENT FOREIGN KEY(USER_ID) REFERENCES PUBLIC.USER(ID) (71)"; SQL statement:
delete from user where id=? [23503-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "FK8KCUM44FVPUPYW6F5BACCX25C: PUBLIC.COMMENT FOREIGN KEY(USER_ID) REFERENCES PUBLIC.USER(ID) (71)"; SQL statement:
delete from user where id=? [23503-200]
@Test
public void commentSave(){
// given
String name="hello00";
Long id=postRepository.findAll(Sort.by("id")).get(0).getId();
String content="반가워요";
// when
Long comment_id=commentService.commentSave(name, id, content);
Comment comment=commentService.findById(comment_id);
// then
assertThat(comment.getUser().getUsername()).isEqualTo("hello00");
assertThat(comment.getComment()).isEqualTo("반가워요");
assertThat(comment.getPost().getId()).isEqualTo(id);
}
COMMENT 테이블과 USER 테이블은 M:1로 매핑되어있다.
지연 로딩을 사용했다.
User user=comment.getUser();
user에 프록시 객체를 넣어둔다.
데이터가 필요할 때가 되어야 데이터베이스를 조회해서 프록시 객체를 초기화
트랜잭션의 범위는 Service와 Repository다.
Comment comment=commentService.findById(comment_id);
findById 메소드 호출 후 영속성 컨텍스트가 이미 끝났다.
트랜잭션이 끝나면 영속성 컨텍스트도 종료된다.
스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용하기 때문이다.
assertThat(comment.getUser().getUsername()).isEqualTo("hello00");
준영속 상태는 영속성 컨텍스트가 없어서 지연 로딩을 시도하면 문제가 발생한다.
✨ 해결
@Test
@Transactional
public void commentSave(){
// given
String name="alswjd00";
Long id=postRepository.findAll(Sort.by("id")).get(0).getId();
String content="반가워요";
// when
Long comment_id=commentService.commentSave(name, id, content);
Comment comment=commentService.findById(comment_id);
// then
assertThat(comment.getUser().getUsername()).isEqualTo("alswjd00");
assertThat(comment.getComment()).isEqualTo("반가워요");
assertThat(comment.getPost().getId()).isEqualTo(id);
}
테스트 메서드에 @Transactional을 붙여서 해결
트랜잭션이 같으면 같은 영속성 컨텍스트를 사용한다.
참고 👇
자바 ORM 표준 JPA 프로그래밍
https://yeon-kr.tistory.com/190
https://programmer-chocho.tistory.com/81
반응형
'ORM > JPA' 카테고리의 다른 글
[JPA] OneToOne (1) | 2024.03.17 |
---|---|
N+1 문제 (0) | 2022.10.27 |
@JoinColumn (0) | 2022.05.19 |
변경 감지(Dirty Checking) (0) | 2022.05.18 |
JPA를 이용한 데이터베이스 초기화 (0) | 2022.03.31 |