Чтобы понять это, вы должны сделать шаг назад. В ОО заказчику принадлежат заказы (заказы представляют собой список в объекте клиента). Не может быть заказа без клиента. Таким образом, клиент, кажется, является владельцем заказов.
Но в мире SQL один элемент будет фактически содержать указатель на другой. Поскольку для N заказов есть 1 клиент, каждый заказ содержит внешний ключ к клиенту, которому он принадлежит. Это «соединение», и это означает, что заказ «владеет» (или буквально содержит) соединение (информация). Это как раз противоположность мира ОО / модели.
Это может помочь понять:
public class Customer {
// This field doesn't exist in the database
// It is simulated with a SQL query
// "OO speak": Customer owns the orders
private List<Order> orders;
}
public class Order {
// This field actually exists in the DB
// In a purely OO model, we could omit it
// "DB speak": Order contains a foreign key to customer
private Customer customer;
}
Обратная сторона является ОО «владельцем» объекта, в данном случае клиентом. У клиента нет столбцов в таблице для хранения заказов, поэтому вы должны указать, где в таблице заказов он может сохранить эти данные (что происходит через mappedBy
).
Другим распространенным примером являются деревья с узлами, которые могут быть как родителями, так и детьми. В этом случае два поля используются в одном классе:
public class Node {
// Again, this is managed by Hibernate.
// There is no matching column in the database.
@OneToMany(cascade = CascadeType.ALL) // mappedBy is only necessary when there are two fields with the type "Node"
private List<Node> children;
// This field exists in the database.
// For the OO model, it's not really necessary and in fact
// some XML implementations omit it to save memory.
// Of course, that limits your options to navigate the tree.
@ManyToOne
private Node parent;
}
Это объясняет «внешний ключ» проектных работ «многие к одному». Существует второй подход, который использует другую таблицу для поддержания отношений. Это означает, что в нашем первом примере у вас есть три таблицы: одна с клиентами, одна с заказами и таблица с двумя столбцами с парами первичных ключей (customerPK, orderPK).
Этот подход является более гибким, чем приведенный выше (он может легко обрабатывать один-к-одному, многие-к-одному, один-ко-многим и даже многие-ко-многим). Цена такова
- это немного медленнее (для поддержки другой таблицы и объединений используются три таблицы вместо двух),
- Синтаксис объединения является более сложным (что может быть утомительно, если вам приходится вручную писать много запросов, например, когда вы пытаетесь что-то отладить)
- это более подвержено ошибкам, потому что вы можете внезапно получить слишком много или слишком мало результатов, если что-то пойдет не так в коде, управляющем таблицей соединений.
Вот почему я редко рекомендую такой подход.