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

주아아빠님의 프로필 이미지

작성한 질문수

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

복합키 있는 테이블 조인시 방법 문의 드립니다.

작성

·

1.9K

1

안녕하세요 강사님~

 

아래와 같은 엔티티가 있다고 가정 할 때

유저정보(ComCorpUser) 조회 시

 

연관관계를 이용해서

유저정보에 연결된 업체코드(BIZ_CD) 조인조건을 걸어서

업체팀코드(ComBizTeam) 를 가져오려고 합니다

 

--█●●--------------------------------------------

COM_CORP_USER (유저정보)

ComCorpUser 클래스

USR_ID 유저아이디

BIZ_CD 업체코드

TEAM_CD 팀코드

--█●●--------------------------------------------

COM_BIZ_TEAM (업체별팀정보)

ComBizTeam

@EmbeddedId

private ComBizTeamPK id;//=>아래 ComBizTeamPK 복합키 사용

BIZ_CD 업체코드

TEAM_CD 팀코드

TEAM_NM 팀명

--█●●--------------------------------------------

COM_BIZ_TEAM (업체별팀정보) 복합키

@Embeddable

public class ComBizTeamPK

BIZ_CD

TEAM_CD

TEAM_NM

--█●●--------------------------------------------

//사용자정보

public class ComCorpUser {

private static final long serialVersionUID = 1L;

@Column(name="BIZ_CD")

private String bizCd;

@Fetch(FetchMode.JOIN)

@ManyToOne

@NotFound(action = NotFoundAction.IGNORE)

@JoinColumn( name="BIZ_CD"

, referencedColumnName ="ID.BIZ_CD"

, insertable=false, updatable=false)

private ComBizTeam comBizTeamInfo;

@Column(name = "TEAM_CD")

private String teamCd;

//업체별팀코드

public class ComBizTeam {

private static final long serialVersionUID = 1L;

@EmbeddedId

private ComBizTeamPK id;

 

//업체별팀코드 복합키

public class ComBizTeamPK implements Serializable{

private static final long serialVersionUID = 1L;

@Column(name="BIZ_CD")

private String bizCd;

@Column(name="TEAM_CD")

private String teamCd;

--█●●--------------------------------------------

JPA 사용시 특정 유저 테이블과 코드성 업체팀코드 테이블 과

조인 조회 시에 @EmbeddedId 복합키와 조인을 하려고 합니다.

구글도 찾아보고,

제가 생각했던 대로 표현을 하면 에러가 발생하네요

 

@JoinColumn 부분

테스트 1. referencedColumnName ="id.BIZ_CD"

=> 서버재시작시에러 Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: id.BIZ_CD in org.hibernate.mapping.Table(COM_BIZ_TEAM) and its related supertables and secondary tables

테스트 2. referencedColumnName ="ID.BIZ_CD"

=> 서버재시작시에러 Unable to find column with logical name: ID.BIZ_CD in org.hibernate.mapping.Table(COM_BIZ_TEAM) and its related supertables and secondary tables

테스트 3. referencedColumnName ="BIZ_CD"

=> 서버재시작시에러

referencedColumnNames(BIZ_CD) of ComCorpUser.comBizTeamInfo referencing ComBizTeam not mapped to a single property

 

질문1.복합키 조인시 뭔가 방법이 있을거 같은데

제가 어떻게 변경해야 하는지 가르침 부탁드립니다.

 

질문2.혹시, 김영한 강사님이 JPA 공부를 위해서 자주 참조 하시는

JPA 관련 해외 잘되어 있는 레퍼런스 사이트나, 좋은 블로그가

있다면 수강생들을 위해 공유 부탁드립니다.

(막힐때 마다 구글링/블로그 뒤지기 전에 만약 알려주시면

그부분에서 먼저 찾아보거나 더 공부 하려고 합니다)

 

감사합니다. 수고하세요

 

#테이블

#조인

#table

#join

#JoinColumn

#EmbeddedId

#join

#컬럼

#여러개

#multiple

#column

#JPA

답변 3

2

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

안녕하세요. 동희님

다음을 참고해주세요. 만약 이 상태로 잘 동작하지 않으면 적어주신 대로 @JoinColumnsOrFormulas도 함께 검토해주세요.

그리고 한가지 팁을 드리자면 뭔가 잘 동작하지 않을 때는 작은 프로젝트를 하나 새로 만들어서 그 작은 프로젝트 안에서 여러가지 테스트와 시도를 해보시는 것을 권장드려요^^ 보통 실무에 있는 코드들은 너무 무겁기 때문에 그곳에 나의 코드를 넣어서 테스트해보려면 시간이 많이 소요될 수 있고, 과감하게 코드를 고치기 어려울 수 있으니까요^^

package com.example.jpacompositekey.entity;

import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "COM_BIZ_TEAM")
public class ComBizTeam {

    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private ComBizTeamPK id;

    @Column(name = "TEAM_NM")
    private String teamNm;

    // Getters and setters
}

package com.example.jpacompositekey.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.Data;

import java.io.Serializable;

@Data
@Embeddable
public class ComBizTeamPK implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name = "BIZ_CD")
    private String bizCd;

    @Column(name = "TEAM_CD")
    private String teamCd;

    // Getters and setters, hashCode, equals
}

package com.example.jpacompositekey.entity;


import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "COM_CORP_USER")
public class ComCorpUser {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "USR_ID")
    private String userId;

    @Column(name = "BIZ_CD")
    private String bizCd;

    @Column(name = "TEAM_CD")
    private String teamCd;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "BIZ_CD", referencedColumnName = "BIZ_CD", insertable = false, updatable = false),
        @JoinColumn(name = "TEAM_CD", referencedColumnName = "TEAM_CD", insertable = false, updatable = false)
    })
    private ComBizTeam comBizTeamInfo;

    // Getters and setters
}


package com.example.jpacompositekey;

import com.example.jpacompositekey.entity.ComBizTeam;
import com.example.jpacompositekey.entity.ComBizTeamPK;
import com.example.jpacompositekey.entity.ComCorpUser;
import com.example.jpacompositekey.repository.ComBizTeamRepository;
import com.example.jpacompositekey.repository.ComCorpUserRepository;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@DataJpaTest
public class JpaTest {

    @Autowired
    private ComCorpUserRepository comCorpUserRepository;

    @Autowired
    private ComBizTeamRepository comBizTeamRepository;

    @Autowired
    EntityManager em;

    @Test
    public void joinComCorpUserAndComBizTeam() {
        // Create and save a ComBizTeam entity
        ComBizTeamPK comBizTeamPK = new ComBizTeamPK();
        comBizTeamPK.setBizCd("BIZ001");
        comBizTeamPK.setTeamCd("TEAM001");

        ComBizTeam comBizTeam = new ComBizTeam();
        comBizTeam.setId(comBizTeamPK);
        comBizTeam.setTeamNm("Team A");

        comBizTeamRepository.save(comBizTeam);

        // Create and save a ComCorpUser entity
        ComCorpUser comCorpUser = new ComCorpUser();
        comCorpUser.setUserId("USR001");
        comCorpUser.setBizCd("BIZ001");
        comCorpUser.setTeamCd("TEAM001");

        comCorpUserRepository.save(comCorpUser);

        em.flush();
        em.clear();

        // 조인된 데이터 조회하기
        ComCorpUser retrievedComCorpUser = comCorpUserRepository.findById("USR001").get();
        assertNotNull(retrievedComCorpUser);
        assertEquals("USR001", retrievedComCorpUser.getUserId());
        assertEquals("BIZ001", retrievedComCorpUser.getBizCd());
        assertEquals("TEAM001", retrievedComCorpUser.getTeamCd());

        ComBizTeam retrievedComBizTeam = retrievedComCorpUser.getComBizTeamInfo();
        assertNotNull(retrievedComBizTeam);
        assertEquals("BIZ001", retrievedComBizTeam.getId().getBizCd());
        assertEquals("TEAM001", retrievedComBizTeam.getId().getTeamCd());
        assertEquals("Team A", retrievedComBizTeam.getTeamNm());
    }
}

감사합니다.

주아아빠님의 프로필 이미지
주아아빠
질문자

강사님 바쁘실 텐데 시간 내셔서 코드까지 작성해주시고 정말 감사합니다.

조언해 주신대로 앞으로 작은 소스에 옮겨서 제가 원하는 부분을

테스트 해보도록 하겠습니다. 고맙습니다. 수고하세요^^

1

주아아빠님의 프로필 이미지
주아아빠
질문자

강사님 안녕하세요~

현재 운영 중인 플랫폼 소스라서 소스는 올리기 어려워서 다음과 같이 다시 질문 드립니다.

 

아래 이미지 봐주세요

 

저는 ComCorpUser.bizCd / teamCd 와

ComBizTeam 에 있는 복합키의

CombizTeamPK 의 속에 있는 bizCd / teamCd 와

연결 고리를 걸어서

다 대 일 단방향 연관관계를 맺고 싶습니다.

세개의 클래스의 java 파일을 어떻게 만들어야 할까요?

 

강사님이 직접 3개의 클래스 java 파일을 만들어서

보여 주실 수 있을까요?

 

급한 질문 아니니 강사님 시간 나실 때 답변주시면 감사하겠습니다

--█●●--------------------------------------------

강사님 아래와 같이 JoinColumnsOrFormulas 이거 사용하니 되는거 같습니다...

public class ComCorpUser extends VluAbstractEntity implements UserDetails {

private static final long serialVersionUID = 1L;

@ManyToOne

@JoinColumnsOrFormulas({

@JoinColumnOrFormula(column = @JoinColumn(name="BIZ_CD", referencedColumnName="BIZ_CD", insertable=false, updatable=false))

,@JoinColumnOrFormula(column = @JoinColumn(name="TEAM_CD", referencedColumnName="TEAM_CD", insertable=false, updatable=false))

})

@NotFound(action=NotFoundAction.IGNORE)

private ComBizTeam comBizTeamInfo;

 

--█●●--------------------------------------------

 

image

 

1

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

안녕하세요. 동희님

전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 실행 방법을 알려주세요.

2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.

감사합니다.