인프런 커뮤니티 질문&답변

한희성님의 프로필 이미지
한희성

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

LazyInitializationException 원인을 알 수 있을까요..

작성

·

532

0

안녕하세요 

양방향 연관관계와 연관관계의 주인 1- 기본 7분 파트 수업 진행중입니다 

Optional<Member> byId = memberRepository.findById(1L);

여기 까진 제대로 호출이 되어 아래 조인이 제대로 수행 되는 것을 확인 하였습니다.

    select

        member0_.member_id as member_i1_1_0_,

        member0_.city as city2_1_0_,

        member0_.name as name3_1_0_,

        member0_.street as street4_1_0_,

        member0_.team_id as team_id6_1_0_,

        member0_.zipcode as zipcode5_1_0_,

        team1_.team_id as team_id1_4_1_,

        team1_.name as name2_4_1_ 

    from

        member member0_ 

    left outer join

        team team1_ 

            on member0_.team_id=team1_.team_id 

    where

        member0_.member_id=?

문제는 다음 소스에서

List<Member> member = byId.get().getTeam().getMembers();

for (Member member1 : member) {
System.out.println(member1.getName());
}

System.out.println() 으로 값을 확인하려하면 예외가 일어나고 있습니다.. ㅠ

맴버 객체

@JoinColumn(name = "team_id")
@ManyToOne(cascade = CascadeType.ALL)
private Team team;

팀 객체

@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();

다음과 같이 설정 하였습니다.

답변 4

0

김영한님의 프로필 이미지
김영한
지식공유자

희성님 많은 부분을 이해하셨군요^^

지금 스프링으로 강의를 따라하고 계신 것이여서 답을 드리자면

@Transactional을 다음과 같이 붙여주세요.

@Service

@Transactional

public class JpaService {}

스프링과 JPA를 함께 사용하면 트랜잭션 범위 안에서 영속성 컨텍스트를 생성하고 관리합니다.

트랜잭션이 종료되면 영속성 컨텍스트도 함께 종료되기 때문에 연관된 엔티티들을 지연로딩(LAZY) 할 수 없습니다.

그래서 LazyInitializationException 예외가 발생한 것이지요.

이 부분에 대한 더 자세한 이해는 프록시 부분에서 설명드립니다.

감사합니다.

0

한희성님의 프로필 이미지
한희성
질문자

바로 다음 강의 듣고 있는 상황에서 에러가 해결과 어느 부분이 잘못되었는지 해결 되었습니다.

디폴트가 lazy 상태라 객체를 사용하는 시점에 영속성에  있지 않아 no session 에러가 나왔으며

@OneToMany(mappedBy = "team",fetch = FetchType.EAGER)
private List<Member> members = new ArrayList<>();

로 수정 후 처음엔 객체 무한 루프가 도는 상황이 발생되더라고요 

바로 다음 강의 양방향 연관관계와 연관관계의 주인 2 - 주의점, 정리  를 듣는 과정에서 

@toString 으로 객체를 확인 할 시 무한루프에 빠진다는 주의점을 깨달았으며

@toString 을 지운 후 

for (Member member1 : members) {
System.out.println(member1.getName());
}

를 호출 시 정상 적으로 객체 탐색이 되는 것을 확인하였습니다.

제가 이해한것이 맞을까요 ?

0

한희성님의 프로필 이미지
한희성
질문자

스프링 부트로 프로젝트를 만들어서 실습중입니다.. 소스가 다시 차이가 있음을 죄송합니다..ㅠㅠ

컨트롤러에서 호출 

package jpabasic.ex1hellojpa.service;

import jpabasic.ex1hellojpa.domain.Member;
import jpabasic.ex1hellojpa.domain.Team;
import jpabasic.ex1hellojpa.repository.JpaTestRepository;
import jpabasic.ex1hellojpa.repository.MemberRepository;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;


@Service
public class JpaService {

final private JpaTestRepository jpaTestRepository;
final private MemberRepository memberRepository;
private JpaService(JpaTestRepository jpaTestRepository
, MemberRepository memberRepository){
this.jpaTestRepository = jpaTestRepository;
this.memberRepository = memberRepository;
}

public void createTest() {
Team team = new Team();
team.setName("team1");
System.out.println("================");
jpaTestRepository.save(team);
System.out.println("================");
System.out.println(team.getId());
System.out.println("테스트");
}


public void createMember() {
Member member = new Member();
member.setName("홍길동");
member.setCity("서울");
member.setZipcode("1234");

Team team = new Team();
team.setName("A ");

member.setTeam(team);
memberRepository.save(member);
System.out.println(member.getId());
}

public void selectMember(){
Optional<Member> byId = memberRepository.findById(1L);
List<Member> members = byId.get().getTeam().getMembers();

for (Member member1 : members) {
//에러
System.out.println(member1.getName());
}

}

}

team 객체

package jpabasic.ex1hellojpa.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@ToString
@Getter
@Setter
@Entity
public class Team {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "team_id")
private Long id;

private String name;

@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}

member 객체

package jpabasic.ex1hellojpa.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.*;

@Getter
@Setter
@ToString
@Entity
public class Member {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;

@JoinColumn(name = "team_id")
@ManyToOne(cascade = CascadeType.ALL)
private Team team;

private String name;

private String city;

private String street;

private String zipcode;
}

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 희성님

main 메서드 전체 코드를 보여주시겠어요?

한희성님의 프로필 이미지
한희성

작성한 질문수

질문하기