누군가 JPA와 Hibernate에서 MappingBy를 설명 할 수 있습니까?


175

나는 최대 절전 모드를 사용하기 때문에 일대 다 관계와 다 대일 관계를 사용해야합니다. 객체에서 양방향 관계이므로 어느 방향에서든 통과 할 수 있습니다. mappedBy권장되는 방법이지만 이해할 수 없습니다. 누군가 설명 할 수 있습니까?

  • 그것을 사용하는 것이 권장되는 방법은 무엇입니까?
  • 어떤 목적으로 해결됩니까?

내 예제를 위해 주석이있는 클래스는 다음과 같습니다.

  • Airline 많은 소유 AirlineFlights
  • 많은 사람들 AirlineFlights하나 에 속합니다 Airline

항공사 :

@Entity 
@Table(name="Airline")
public class Airline {
    private Integer idAirline;
    private String name;

    private String code;

    private String aliasName;
    private Set<AirlineFlight> airlineFlights = new HashSet<AirlineFlight>(0);

    public Airline(){}

    public Airline(String name, String code, String aliasName, Set<AirlineFlight> flights) {
        setName(name);
        setCode(code);
        setAliasName(aliasName);
        setAirlineFlights(flights);
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="IDAIRLINE", nullable=false)
    public Integer getIdAirline() {
        return idAirline;
    }

    private void setIdAirline(Integer idAirline) {
        this.idAirline = idAirline;
    }

    @Column(name="NAME", nullable=false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = DAOUtil.convertToDBString(name);
    }

    @Column(name="CODE", nullable=false, length=3)
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = DAOUtil.convertToDBString(code);
    }

    @Column(name="ALIAS", nullable=true)
    public String getAliasName() {
        return aliasName;
    }
    public void setAliasName(String aliasName) {
        if(aliasName != null)
            this.aliasName = DAOUtil.convertToDBString(aliasName);
    }

    @OneToMany(fetch=FetchType.LAZY, cascade = {CascadeType.ALL})
    @JoinColumn(name="IDAIRLINE")
    public Set<AirlineFlight> getAirlineFlights() {
        return airlineFlights;
    }

    public void setAirlineFlights(Set<AirlineFlight> flights) {
        this.airlineFlights = flights;
    }
}

항공사 :

@Entity
@Table(name="AirlineFlight")
public class AirlineFlight {
    private Integer idAirlineFlight;
    private Airline airline;
    private String flightNumber;

    public AirlineFlight(){}

    public AirlineFlight(Airline airline, String flightNumber) {
        setAirline(airline);
        setFlightNumber(flightNumber);
    }

    @Id
    @GeneratedValue(generator="identity")
    @GenericGenerator(name="identity", strategy="identity")
    @Column(name="IDAIRLINEFLIGHT", nullable=false)
    public Integer getIdAirlineFlight() {
        return idAirlineFlight;
    }
    private void setIdAirlineFlight(Integer idAirlineFlight) {
        this.idAirlineFlight = idAirlineFlight;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="IDAIRLINE", nullable=false)
    public Airline getAirline() {
        return airline;
    }
    public void setAirline(Airline airline) {
        this.airline = airline;
    }

    @Column(name="FLIGHTNUMBER", nullable=false)
    public String getFlightNumber() {
        return flightNumber;
    }
    public void setFlightNumber(String flightNumber) {
        this.flightNumber = DAOUtil.convertToDBString(flightNumber);
    }
}

편집하다:

데이터베이스 스키마 :

AirlineFlights에는 idAirline이 ForeignKey로 있고 Airline에는 idAirlineFlights가 없습니다. 이것은 AirlineFlights를 소유자 / 식별 기관으로 만드는가?

이론적으로는 AirlinesFlights의 항공사가되기를 바랍니다.

여기에 이미지 설명을 입력하십시오

답변:


151

@JoinColumn두 모델을 모두 지정하면 양방향 관계가 없습니다. 당신은 두 가지 일방적 인 관계를 가지고 있으며, 그 점에서 매우 혼란스러운 매핑이 있습니다. 두 모델 모두 IDAIRLINE 열을 "소유"한다고 말하고 있습니다. 실제로 그들 중 하나만이 실제로해야합니다! '정상적인'것은 측면에서 완전히 @JoinColumn벗어난 @OneToMany대신 mapBy를에 추가하는 것 @OneToMany입니다.

@OneToMany(cascade = CascadeType.ALL, mappedBy="airline")
public Set<AirlineFlight> getAirlineFlights() {
    return airlineFlights;
}

이것은 Hibernate에게 "구성을 찾기 위해 수집 한 것들에 대해 'airline'이라는 빈 프로퍼티를 살펴 보라고한다."


2
MapsBy에 대한 설명에서 약간 혼란 스럽습니다. db에서 일이 어떻게 구성되어 있는지 중요합니까? @DB : AirlineFlights에는 외래 키로 idAirline이 있습니다. 항공사는 단지 기본 키로 idAirline을 가지고 있으며 AirlineFlights @ DB에 대한 정보를 관리하지 않습니다.
brainydexter

10
그렇습니다. MappingBy의 이름은 Hibernate에게 JoinColumn의 구성을 찾을 위치를 알려줍니다. AirlineFlight의 getAirline () 메소드에서 JoinColumn을 항공사에 배치하여 맵핑 한 방식으로 Airline 에 다른 테이블의 값을 유지 보수 할 책임 있음을 알려 줍니다. Entity에게 다른 테이블의 열을 "소유"하고 업데이트를 담당 할 수 있습니다. 일반적으로 수행하려는 작업이 아니며 SQL 문 실행 순서에 문제가 발생할 수 있습니다.
Affe

편집 내용을 참조하십시오. DB 수준에서 airlineFlight 테이블은 idAirline을 외래 키 열로 소유합니다. 따라서 JoinColumn은 해당 열을 소유하고 있기 때문에 해당 ManytoOne의 airlineFlight 클래스 / 테이블에 배치해야합니까?
brainydexter

예, 그렇게하는 것이 좋습니다. 가장 복잡한 옵션이며 다른 것이 필요하지 않은 것 같습니다.
Affe

"@OneToMany 쪽에서 @JoinColumn을 완전히 빼내십시오"라는 @ManyToOne말이 맞습니까?
nbro

284

MappedBy는 관계의 키가 다른쪽에 있다는 것을 동면합니다.

즉, 2 개의 테이블을 서로 연결하더라도 해당 테이블 중 1 개만 다른 테이블에 외래 키 제약 조건을 갖습니다. MappedBy를 사용하면 제약 조건이없는 테이블에서 다른 테이블로 계속 연결할 수 있습니다.


3
좀 더 설명해 주시겠습니까?
Alexander Suraphel

1
@ Kurt Du Bois, 왜 mappedBy양방향을 정의 하기 보다는 왜 사용 합니까 (각 측면에 foreign_key 제약 조건이 있습니까)?
케빈 메러디스

6
때로는 양쪽에 열쇠를 두는 것이 의미가 없기 때문입니다. 예를 들어 회사와 휴대용 컴퓨터가 있다고 가정 해보십시오. 휴대용 컴퓨터는 한 회사에만 속하지만 회사에는 여러 휴대용 컴퓨터가 있습니다.
Kurt Du Bois

내 답변을 롤백 한 편집 담당자에게 죄송하지만 실제로 편집에는 부가 가치가 없었습니다. 마지막 문장도 이해가되지 않았습니다.
Kurt Du Bois

@KurtDuBois는 데이터베이스를 작성하는 방법에 대해서만 그림으로 만 들어옵니다. 즉, 자바로 매핑되거나 매핑되지 않은 ur가 비슷한 방식으로 작동합니다.

22

mappedby최대 절전 모드에서는이 필드를 매핑하지 않도록합니다. 이미이 필드 [name = "field"]에 의해 매핑되었습니다.
필드가 다른 엔터티에 있습니다 (name of the variable in the class not the table in the database).

그렇게하지 않으면 최대 절전 모드는이 두 관계를 동일한 관계가 아니기 때문에 매핑합니다

따라서 한면에서만 매핑을 수행하고 그 사이를 조정하도록 최대 절전 모드를 설정해야합니다.


mapBy는 선택 사항입니까? MapsBy를 사용하지 않기 때문에 동일한 결과, 즉 양방향 객체 매핑을 얻습니다
Freelancer

당신은 당신이 한면에 mappedBy를 사용할 필요가 many2many의 측면 같은 일 중 하나에 mappedBy를 사용하지 않고 on2many 및 many2one 사용할 수 없습니다
Charif DZ

다른 테이블의 필드 이름 인 속성 값의 의미를 지적 해 주셔서 감사합니다.
Gab 是 好人

2
아마 최대 절전 모드는 항상 스스로를 말하지는 않지만 적어도 구두점을 사용합니다
Amalgovinus

1
나를 위해, 그것은 스스로를 말하지 않습니다. 반대로 매우 혼란 스럽다. 다만 실제로 무엇인지에 관한 질문의 양을보고 mappedBy하고 inversedBy. 다른 ORM들을 훨씬 더 지능적인 사용 belongsToMany, hasMany속성.
Jan Bodnar

12

Mappingby = "다른 클래스에서 생성 된 동일한 클래스의 개체"

참고 :-매핑 기준은 하나의 테이블에 외래 키 제약 조건이 있어야하므로 한 클래스에서만 사용할 수 있습니다. 에 의해 매핑 될 수 있다면 양쪽 테이블에서 외래 키를 제거하고 외래 키없이 두 테이블 사이의 관계는 없습니다.

참고 :-다음 주석에 사용할 수 있습니다 :-1. @ OneTone 2. @ OneToMany 3. @ ManyToMany

참고 --- 다음 주석에는 사용할 수 없습니다 :-1. @ ManyToOne

일대일 :-매핑의 어느 한 쪽에서 수행하지만 한 쪽에서 만 수행하십시오. 클래스가 적용되는 테이블에서 외래 키 제약 조건의 추가 열을 제거합니다.

예를 들어. 직원 객체에서 직원 객체의 매핑을 적용하면 직원 테이블의 외래 키가 제거됩니다.


12

테이블 관계와 엔티티 관계

관계형 데이터베이스 시스템에서 one-to-many테이블 관계 는 다음과 같습니다.

<code> 일대 다 </ code> 테이블 관계

관계는 post_id자식 테이블 의 외래 키 열 (예 :)을 기반으로 합니다.

따라서 one-to-many테이블 관계 를 관리 할 때 진실의 원천이 있습니다.

이제 one-to-many이전에 보았던 테이블 관계 에 맵핑되는 양방향 엔티티 관계를 사용하는 경우 :

양방향 <code> 일대 다 </ code> 엔티티 연결

위의 다이어그램을 보면이 관계를 관리하는 두 가지 방법이 있음을 알 수 있습니다.

에서 Post엔티티, 당신은이 comments모음 :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

그리고 PostComment에서 post연결은 다음과 같이 매핑됩니다.

@ManyToOne(
    fetch = FetchType.LAZY
)
@JoinColumn(name = "post_id")
private Post post;

외래 키 열을 나타내는 두 가지 방법이 있기 때문에 연결 상태 변경을 해당 외래 키 열 값 수정으로 변환 할 때 진실의 원인을 정의해야합니다.

매핑

mappedBy속성은@ManyToOne 측면이 외래 키 열 관리를 담당하고 컬렉션은 하위 엔터티를 가져오고 상위 엔터티 상태 변경을 하위 항목으로 계단식으로 데만 사용됩니다 (예 : 상위를 제거하면 하위 엔터티도 제거해야 함).

양방향 연관의 양쪽을 동기화

이제 mappedBy속성 을 정의하고 하위 측 @ManyToOne연결이 외래 키 열을 관리하더라도 양방향 연결의 양쪽을 동기화해야합니다.

이를 수행하는 가장 좋은 방법은 다음 두 가지 유틸리티 방법을 추가하는 것입니다.

public void addComment(PostComment comment) {
    comments.add(comment);
    comment.setPost(this);
}

public void removeComment(PostComment comment) {
    comments.remove(comment);
    comment.setPost(null);
}

addCommentremoveComment방법은 양측이 동기화되어 있는지 확인합니다. 따라서 자식 엔터티를 추가하면 자식 엔터티가 부모를 가리켜 야하며 부모 엔터티는 자식 컬렉션에 자식이 포함되어 있어야합니다.

모든 양방향 엔티티 연관 유형을 동기화하는 가장 좋은 방법에 대한 자세한 내용은 이 기사를 확인 하십시오 .


0

ManyToOne mapping으로 시작한 다음 BiDirectional 방식으로 OneToMany 매핑을 추가했습니다. 그런 다음 OneToMany 측 (일반적으로 부모 테이블 / 클래스)에서 "mappedBy"(자식이 자식 테이블 / 클래스에 의해 매핑 됨)를 언급해야하므로 최대 절전 모드에서는 DB에 EXTRA 매핑 테이블이 생성되지 않습니다 (TableName = parent_child 등).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.