Попытка понять важность отношения «один-много» в ORM - PullRequest
7 голосов
/ 20 декабря 2011

Несмотря на то, что мой вопрос сформулирован специально о том, как отношения сущностей изображаются в платформе Play, которая использует Hibernate, я уверен, что это общая концепция.

Когда у нас отношения один-ко-многим, нас всегда просят указать сторону владельца.

Так, например, если бы у нас были отношения один-ко-многим между Person и PhoneNumber, мы бы написали такой код.

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

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

В приведенном выше коде объектом-владельцем является PhoneNumber. Каковы плюсы и минусы обеих сторон, являющихся собственностью?

Я понимаю, что когда объектом-владельцем является PhoneNUmber, представленное отношение представляет собой ManyToOne, что не приведет к соединению таблицы, в то время как когда сторона-владелец представляет собой Person, отображаемое отношение будет OneToMany, и в этом случае таблица отношения будет создано.

Является ли это основной причиной определения стороны-владельца или есть и другие причины?

Обновление: Я только что понял, что эта тема дает часть ответа, но я надеюсь, что могут быть и другие моменты.

Ответы [ 2 ]

6 голосов
/ 20 декабря 2011

Важным моментом, который следует иметь в виду, является то, что отношение-владелец является тем, которое действительно сохраняет отношение при сохранении.Например:

    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
1 голос
/ 20 декабря 2011

С большинством слоев ORM у вас есть концепция отложенной загрузки. Когда вы создаете объект Person, он не будет загружать установленные телефоны без соответствующего запроса. Время от времени, как вы хотите искать данные, также может диктовать, как вы храните их.

Например, если вы хотите сначала вызвать человека, а затем показать телефонные номера по требованию, тогда сохранение личных справок в телефоне - это хорошо. Сначала вы запускаете простой запрос для загрузки личных данных, а затем просто просматриваете телефонные номера на основе (уже загруженного) person.id (еще один простой запрос)

Принимая во внимание, что для отображения данных о человеке + телефоне за один раз, вы бы предпочли иметь таблицу соединений, в которую можно просто загружать данные на основе таблицы «человек + телефон» с использованием идентификатора человека в качестве ключей в телефонной таблице, и все сразу. , Здесь было бы дорого делать поиск без таблицы отношений.

Но, честно говоря, если вы думаете, что SQL вместо ORM, то вы бы каждый раз использовали таблицу отношений: D

...