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

epfvkdlxj1님의 프로필 이미지

작성한 질문수

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

영속성 컨텍스트와 LAZY 로딩 관계

작성

·

261

0

안녕하세요. 영한님
강의를 듣고 궁금한점이 있어서 질문드립니다.
영속성 컨텍스트와 Proxy, LAZY 강의를 들었을 때 Member 엔티티안에 Team 엔티티를 필드로 가지고 있고, LAZY로 연관관계를 설정하였을 때 , Member만 조회하였을 때는 Team은 아직까지 Proxy객체에 null로 있고, Team의 데이터를 조회했을 때 Proxy객체가 Team 객체를 참조하는걸로 이해했습니다. 그렇다면 Team의 객체가 null로 초기화 되어있다가 조회한 데이터로 초기화되는걸로 이해했습니다. 아니면 그냥 Select 쿼리만 나오고 Team proxy객체는 계속해서 null이고 Team 데이터를 조회 할 때만 select쿼리만 호출되는걸까요..?

List<FMSCompany> contents = companies.getContent();
for (int i = 0; i < contents.size(); i++)
        {
            FMSCompany company = contents.get(i);
            FMSBranch branch = company.getBranches().stream().filter(fmsBranch -> Objects.equals(fmsBranch.getId(), company.getHqBranchId())).findFirst().get();
            System.out.println(branch.getLocation() +", "+ branch.getCompany().getId() +", "+ branch.getBusinessRegistrationNumber() );
        }

}

public class FMSCompany extends AbstractCompany
{

    @JsonManagedReference
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = CascadeType.ALL)
    private List<FMSBranch> branches = new ArrayList<>();

    @JsonManagedReference
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "company", cascade = CascadeType.ALL)
    private List<FMSBranchGarage> garages = new ArrayList<>();

    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "hqBranchId", foreignKey = @ForeignKey(name = "fk_fms_company__fms_branch__id"))
    private FMSBranch hqBranch;

    @Column(insertable = false, updatable = false, columnDefinition = "BIGINT(20) COMMENT '본사 아이디'")
    private Long hqBranchId;

    // ATTRIBUTENAME: owner -> boss, ownerId -> bossId
    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
    @JoinColumn(name = "ownerId", foreignKey = @ForeignKey(name = "fk_fms_company__fms_user__id"))
    @ToString.Exclude
    private FMSUser owner;

    @Column(columnDefinition = "TINYINT(1) DEFAULT 1 COMMENT '삭제 여부 (0: 삭제 안 함, 1: 삭제)'")
    private Boolean isDeleted = Boolean.FALSE;

    @Column(columnDefinition = "DATETIME DEFAULT NULL COMMENT '마지막 삭제 일시'")
    private LocalDateTime lastDeletedDateTime;

    // ATTRIBUTENAME: grantedRoles -> roles
    // @formatter:off
    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
    @ToString.Exclude
    @JoinTable
    (
        name = "fms_company_role",
        indexes =
        {
            @Index(name = "idx_fms_company_id", columnList = "fms_company_id"),
            @Index(name = "idx_role_id", columnList = "role_id"),
        },
        joinColumns = @JoinColumn(name = "fms_company_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "fk_fms_company_role__fms_company__id")),
        inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "fk_fms_company_role__role__id"))
    )
    private List<Role> grantedRoles;
}
public class FMSBranch extends AbstractEntity
{

    @Column(columnDefinition = "VARCHAR(20) COMMENT '지점 이름'", length = 20)
    private String name;

    @Column(columnDefinition = "VARCHAR(15) COMMENT '사업자등록번호'")
    private String businessRegistrationNumber;

    @Column(columnDefinition = "TEXT COMMENT '주소'")
    private String address;

    @Embedded
    private Location location;

    @Column(columnDefinition = "VARCHAR(20) COMMENT '연락처'")
    private String phone;

    @Column(columnDefinition = "TEXT COMMENT '설명'")
    private String description;
    // @Column(columnDefinition = "VARCHAR(20) COMMENT '조직 유형 (HEADQUARTER: 본점, AGENT_OFFICE: 지점)'")
    // @Enumerated(value = EnumType.STRING)
    // private Organization organization;
    //
    // @Column(columnDefinition = "VARCHAR(20) COMMENT '지점 상태 (NORMAL: 정상, BLOCKED: 정지)'")
    // @Enumerated(value = EnumType.STRING)
    // private ServiceStatus status;

    @Column(columnDefinition = "TINYINT(2) COMMENT '조직 유형 (0 - HEADQUARTER: 본점, 1 - AGENT_OFFICE: 지점)'")
    @Convert(converter = OrganizationConverter.class)
    private Organization organization;

    @Column(columnDefinition = "TINYINT(2) COMMENT '상태 (0 - BLOCKED: 정지, 1 - NORMAL: 정상)'")
    @Convert(converter = ServiceStatusConverter.class)
    private ServiceStatus status;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
    @JoinColumn(name = "ownerId", foreignKey = @ForeignKey(name = "fk_fms_branch__fms_user__id"))
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    private FMSUser owner;

    @Column(columnDefinition = "BIGINT(20) COMMENT '소유자 아이디'", insertable = false, updatable = false)
    private Long ownerId;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
    @JoinColumn(name = "companyId", foreignKey = @ForeignKey(name = "fk_fms_branch__fms_company__id"))
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    private FMSCompany company;

    @Column(columnDefinition = "BIGINT(20) COMMENT '업체 아이디'", insertable = false, updatable = false)
    private Long companyId;

    @Column(columnDefinition = "TINYINT(1) DEFAULT 1 COMMENT '삭제 여부 (0: 삭제 안 함, 1: 삭제)'")
    private Boolean isDeleted = Boolean.FALSE;

    @Column(columnDefinition = "DATETIME DEFAULT NULL COMMENT '마지막 삭제 일시'")
    private LocalDateTime lastDeletedDateTime;

    @JsonManagedReference
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "fmsBranch", cascade = CascadeType.ALL)
    private FMSBranchPushStatus fmsBranchPushStatus;

    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Transient
    private String companyName;

    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Transient
    private CountInBranchDTO count;

    @JsonManagedReference
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "branch", cascade = CascadeType.ALL)
    private List<FMSBranchGarage> garages = new ArrayList<>();
}

 

FMSBranch의 데이터를 조회를 했음에도 불구하고 FMSBranch Proxy는 계속해서 null로 초기화 되어있습니다..

답변 1

0

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

안녕하세요. epfvkdlxj1님^^

proxy 객체의 필드는 초기화와 무관하게, 항상 null입니다. 메서드를 호출해서 target을 조회하는 것 뿐입니다.

관련해서 프록시 부분을 다시 복습하시면 이해가 되실거에요.

감사합니다.

epfvkdlxj1님의 프로필 이미지
epfvkdlxj1
질문자

넵! 감사합니다. 한번 더 복습을 해야겠습니다. 답변 감사합니다 :)