잘만되던 CRUD가 갑자기 안되기 시작했다.
DB에 저장된 정보 불러오기(Get)을 할 때 이런 문제를 발견했다.
1. 문제 정의
아니 왜 안돼??? 젠장 또 에러메시지야..
LazyInitializationException : could not initialize proxy - no Session
즉, 프록시를 시작할 수 없다 그말씀이시네요.
프록시 문제인 것을 보니 아무래도 JPA 연관관계 매핑에서 오류가 난 듯하다.
2. 해결방안 접근
JPA 연관관계 매핑을 해 둔 엔티티로 가보자.
현재 Professor - Major 가 1:1 연관관계를 맺고 있다. (Professor가 major_ID 를 FK로 갖고 있는 구조다)
아무래도 위 사진에서 major 객체를 OneToOne으로 연관관계 매핑해줄 때 문제가 생긴 듯 하다.
이전까진 문제 없었는데,,,,(왜 문제가 없었냐면 major 객체가 아니라 그냥 majorId,majorName 쌩으로 받았었거든 크크)
원래했던 것처럼 major의 인자(id,name 등)를 쌩으로 받는 것은 제대로된 연관관계 매핑이 아니므로,
(스프링이 major와 Professor가 연관관계임을 인지하지 못함 -> 매번 professor 조회 시join을 써줘야하는 번거러움-> 생산성 저하)
Major 객체를 받아 @OneToOne으로 묶어줬는데, 이 사단이 난 것.
이 설명을 왜하냐면,
1. 위처럼 Major 객체를 받아와 연관관계를 매핑해주고,
2. 지연로딩(Lazy)를 걸어주게되면!
Professor 엔티티를 불러올 때 매핑된 Major 엔티티까지 굳이 안불러와도 되기 때문이다.
굳이 안불러오는 대신 Major 객체 역할을 하는 "대리"객체 -> 프록시 객체를 생성해두는 것 (프록시를 해석하면 대리라는 뜻이다)
즉 Professor 엔티티 호출할 땐 Major 엔티티를 안불러오고 일단 프록시 객체로 생성하도록 JPA가 설정해놓고 있는 것(Professor 정보만 필요한 데 굳이 Major정보까지 불러오는 것은 비용이 드니깐, Major가 필요해질 때 부르겠다 이말이여)
그래서 본론으로 돌아와서 에러메시지를 보면,
LazyInitializationException : could not initialize proxy - no Session
그래그래 프록시 실행을 못했다는 거징
그럼 왜 못했냐!
보통 하나의 트랜잭션을 하나의 영속성 컨택스트로 대입하는데, 트랜잭션에서 벗어나서 작업이 진행됐거나, 애초에 프록시 객체가 없거나.
둘 중 하나다.
일단 넣어드렸습니다.
@Transactional 어노테이션을 넣어주면,
- 클래스, 메소드에 @Transactional 선언 시 해당 클래스,메서드에 트랜잭션이 적용된 프록시 객체 생성
- 프록시 객체는 @Transactional이 포함된 메서드가 호출될 경우, 트랜잭션을 시작하고 Commit or Rollback을 수행
프록시 객체를 만들어준다!
잘되신다.
프록시 객체가 없어서 에러가 떴던 걸로 확인했다.
참고로, 컨트롤러에서 엔티티 그대로 리턴하고 DTO로 컨트롤러에서 변환하면 문제생긴다. (영속성 컨텍스트에서 컨트롤러는 제외)
'Development > TrobleShooting' 카테고리의 다른 글
Boolean true == "true"가 가능할까요? (4) | 2024.06.13 |
---|---|
[Gasip Project] 왜 Column Name이 중복이라고 뜨죠? _ DuplicateMappingException (2) | 2023.11.05 |
[Git] Push가 안되는 이유는? git remote : Permission to ---The requested URL returned error: 403 (6) | 2023.10.16 |
@Autowired에 빨간줄이 그어진 이유 (4) | 2023.10.10 |
인텔리제이 read-only가 안풀려서 도저히 코딩을 못하겠다. (0) | 2023.09.07 |