В этих примерах на Ссылке на примечание TopLink JPA:
Пример 1-59 @OneToMany - клиентский класс с дженериками
@Entity
public class Customer implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="customer")
public Set getOrders() {
return orders;
}
...
}
Пример 1-60 @ManyToOne - класс порядка с дженериками
@Entity
public class Order implements Serializable {
...
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
return customer;
}
...
}
Мне что кажется Customer
объект является владельцем ассоциации. Однако в объяснении mappedBy
атрибут в том же документе, это записано это:
если отношения двунаправлены, то установленный mappedBy элемент на обратном (невладение) сторона ассоциации к названию поля или свойства, которое владеет отношениями как Примером 1-60 шоу.
Однако, если я не ошибаюсь, это похоже в примере, mappedBy
на самом деле указан на стороне владения ассоциации, а не стороне невладения.
Таким образом, мой вопрос в основном:
В двунаправленной (one-to-many/many-to-one) ассоциации, которая из объектов является владельцем? Как мы можем определять Одну сторону как владельца? Как мы можем определять сторону Многих как владельца?
Что предназначено "обратной стороной ассоциации"? Как мы можем определять Одну сторону как инверсию? Как мы можем определять сторону Многих как инверсию?
Чтобы понять это, нужно сделать шаг назад. В OO заказчик владеет заказами (заказы представляют собой список в объекте клиента). Без покупателя не может быть заказа. Таким образом, клиент выглядит владельцем заказов.
Но в мире 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).
Этот подход более гибкий, чем описанный выше (он может легко обрабатывать запросы «один к одному», «многие к одному», «один ко многим» и даже «многие ко многим»).Цена в том, что
Вот почему я редко рекомендую этот подход.