2011-12-20 2 views
7

내 질문에 Hibernate를 사용하는 Play 프레임 워크에 엔티티 관계가 묘사 된 방식이 구체적으로 언급되었지만, 이것이 일반 개념.ORM에서 one-many 관계의 소유 측면의 중요성을 이해하려고 시도합니다.

우리는 일대 다 관계를 가질 때 항상 소유 측면을 지정해야합니다.

Person과 PhoneNumber 사이에 일대일 관계가 있다면 예를 들어 다음과 같은 코드를 작성합니다.

@Entity 
class Person { 
    @OneToMany(mappedBy="person") 
    public Set<PhoneNumber> phoneNumbers; 
} 

@Entity 
class PhoneNumber { 
    @ManyToOne 
    public Person person; 
} 

위의 코드에서 소유하는 엔터티는 PhoneNumber입니다. 소유주가되는 양측의 장단점은 무엇입니까?

소유자 엔티티가 PhoneNUmber 인 경우 실현 된 관계는 ManyToOne이며 조인 테이블을 생성하지 않습니다. 반면 소유면이 Person 인 경우 묘사 된 관계는 OneToMany가됩니다.이 경우 관계 테이블은 만들 수 있습니다.

소유 측면을 결정하는 주된 이유입니까 아니면 다른 이유가 있습니까?

업데이트 : 난 그냥 this thread 대답의 일부를 제공하는 것을 깨달았지만, 나뿐만 아니라 다른 지점이있을 수 있습니다 기대하고있다.

답변

1

대부분의 ORM 레이어에는 지연로드 개념이 있습니다. Person 객체를 만들면 요청하지 않으면 전화기가로드되지 않습니다. 데이터 조회 방법은 저장 방법에 따라 달라질 수 있습니다.

사람을 먼저 불러 와서 전화 번호를 보여주고 싶으면 전화로 사람 참조를 유지하는 것이 좋습니다. 먼저 사람 데이터를로드 한 다음 (이미로드 된) person.id (다른 간단한 쿼리)를 기반으로 전화 번호를 조회하는 간단한 쿼리를 실행합니다.

한 번에 사람 + 전화 데이터를 표시하려면 당신이 사람 테이블을 기반으로 데이터를로드 할 수있는 조인 테이블 - person-phone 전화 테이블에 사람 ID를 키로 사용하는 테이블 조인, 한 번에 모두. 여기에서는 관계 테이블없이 조회하는 것이 비용이 많이들 것입니다.

그러나 대신 ORM의 SQL은 다음의 관계 테이블마다 갈 것이라고 생각하면 솔직히 : 염두에두고 D

+0

나는 소리내어 생각하고있다. 두 경우 모두 열심히 가져옵니다. 첫 번째 경우 PhoneNumber가 소유하는 엔터티의 경우 모든 Person 엔터티를 가져 오는 첫 번째 쿼리를 실행 한 다음 각 Person에 대한 개별 쿼리를 실행하여 해당 Person에 대한 모든 PhoneNumber를 가져옵니다. 그러나 Person을 소유 측으로 가지고 있다면 조인과 함께 하나의 쿼리 만 실행하면됩니다. 이것이 바보 같은 질문이라면 유감 스럽지만 Person이 PhoneNumber에서 FK가되는 것은 불가능합니다. – Parag

+0

예, 전화 테이블의 사람 ID FK를 사용하여 조인을 수행 할 수 있어야합니다.여기에서는 정규화 된 조회가 더 빠를 것이라고 가정하지만 가정은 설명 계획을 확인해야합니다. 관계 테이블을 사용하는 또 다른 이유는 (적어도 이론적 인) 교대로 두 사람이 사용하는 전화 번호와 같은 전화 번호 공유를 허용하는 것입니다. 솔직히 ORM 레이어가 어떻게 작동하는지는 아무리 생각해도 ORM 레이어가있는 스키마를 설계하지 않기 때문에 – rjha94

+0

'mappedBy'및 'owning side'라는 이름의 이유 때문에이 스레드에서도 내 답변을 볼 수 있습니다. 소유 사이드를 정의하지 않으면 GOTCHAs - http://stackoverflow.com/questions/2749689/what-is-the-owning-side-in-an-orm-mapping/21068644#21068644 –

6

중요한 점을 소유 관계가 실제로 지속 한 점이다 관계에 대한 관계. 당신은 당신이 어떤 숫자를 볼 수 있습니다 데이터베이스에서 개체를 다시로드하면

Person person = new Person(); 
    PhoneNumber pn = new PhoneNumber(); 
    pn.phone = "12345678"; 
    person.phoneNumbers.add(pn); 
    session.save(person); 

는 관계가 가리키고 저장되지 않습니다 예를 들어와. 관계를 실제로 추가하려면 소유자 측 (PhoneNumber)에 사람을 설정하고 저장해야합니다.

// the relation is not saved 
    Person loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 0! 

    pn.person = person; 
    session.save(pn); 

    loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 1 
관련 문제