JPA: разница между @JoinColumn и @PrimaryKeyJoinColumn?
Какая точная разница между @JoinColumn
а также @PrimaryKeyJoinColumn
?
Ты используешь @JoinColumn
для столбцов, которые являются частью внешнего ключа. Типичный столбец может выглядеть следующим образом (например, в таблице соединений с дополнительными атрибутами):
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;
Что произойдет, если я продвигаю столбец, чтобы он тоже был / PK? Поскольку столбец теперь PK, я должен пометить его @Id
:
@Id
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;
Теперь вопрос:
Являются @Id
+ @JoinColumn
так же, как и просто @PrimaryKeyJoinColumn
?:
@ManyToOne
@PrimaryKeyJoinColumn(name = "...")
private OtherClass oc;
Если нет, то что @PrimaryKeyJoinColumn
там для?
4 ответа
Что произойдет, если я продвигаю столбец, чтобы он тоже был / PK? Поскольку столбец теперь PK, я должен пометить его @Id (...).
Эта расширенная поддержка производных идентификаторов фактически является частью нового материала в JPA 2.0 (см. Раздел 2.4.1 Первичные ключи, соответствующие производным идентификаторам в спецификации JPA 2.0), JPA 1.0 не позволяет Id
на OneToOne
или же ManyToOne
, С JPA 1.0 вам придется использовать PrimaryKeyJoinColumn
а также определить Basic
Id
отображение для столбца внешнего ключа.
Теперь возникает вопрос: являются ли @Id + @JoinColumn такими же, как просто @PrimaryKeyJoinColumn?
Вы можете получить аналогичный результат, но используя Id
на OneToOne
или же ManyToOne
намного проще и является предпочтительным способом сопоставления производных идентификаторов с JPA 2.0. PrimaryKeyJoinColumn
может по-прежнему использоваться в стратегии СОЕДИНЕННОГО наследования. Ниже соответствующего раздела из спецификации JPA 2.0:
11.1.40 PrimaryKeyJoinColumn Annotation
PrimaryKeyJoinColumn
аннотация указывает столбец первичного ключа, который используется в качестве внешнего ключа для соединения с другой таблицей.
PrimaryKeyJoinColumn
аннотация используется для присоединения к основной таблице подкласса сущности вJOINED
отображение стратегии на первичную таблицу своего суперкласса; он используется вSecondaryTable
аннотация для присоединения вторичной таблицы к первичной таблице; и это может быть использовано вOneToOne
отображение, при котором первичный ключ ссылающегося объекта используется в качестве внешнего ключа для ссылочного объекта [108]....
Если нет
PrimaryKeyJoinColumn
аннотация указывается для подкласса в стратегии отображения JOINED, предполагается, что столбцы внешнего ключа имеют те же имена, что и столбцы первичного ключа первичной таблицы суперкласса....
Пример: подкласс Customer и ValuedCustomer
@Entity @Table(name="CUST") @Inheritance(strategy=JOINED) @DiscriminatorValue("CUST") public class Customer { ... } @Entity @Table(name="VCUST") @DiscriminatorValue("VCUST") @PrimaryKeyJoinColumn(name="CUST_ID") public class ValuedCustomer extends Customer { ... }
[108] Механизмы производных идентификаторов, описанные в разделе 2.4.1.1, теперь предпочтительнее, чем
PrimaryKeyJoinColumn
для случая сопоставления OneToOne.
Смотрите также
Этот источник http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state утверждает, что использование @ManyToOne и @Id работает с JPA 1.x. Кто сейчас прав?
Автор использует предварительную версию JPA 2.0, совместимую с EclipseLink (версия 2.0.0-M7 на момент написания статьи), чтобы написать статью о JPA 1.0(!). Эта статья вводит в заблуждение, автор использует что-то, что НЕ является частью JPA 1.0.
Для записи, поддержка Id
на OneToOne
а также ManyToOne
был добавлен в EclipseLink 1.1 (см. это сообщение от Джеймса Сазерленда, комментатора EclipseLink и основного автора вики-книги Java Persistence). Но позвольте мне настаивать, это не является частью JPA 1.0.
Я обычно различаю эти два с помощью этой диаграммы:
использование PrimaryKeyJoinColumn
использование JoinColumn
Я знаю, что это старый пост, но сейчас хорошее время PrimaryKeyColumn
было бы, если бы вы хотели однонаправленную связь или имели несколько таблиц с одним и тем же идентификатором.
В общем, это плохая идея, и было бы лучше использовать отношения внешнего ключа с JoinColumn
.
При этом, если вы работаете со старой базой данных, в которой использовалась подобная система, то сейчас самое время ее использовать.
Вы используете @JoinColumn, когда хотите управлять (изменить имя столбца, установить значение nullable и т. д.) столбцом внешнего ключа в целевой таблице сущностей. Здесь таблица адресов будет содержать идентификатор таблицы пользователей, такой как внешний ключ, но столбец будет иметь имя user_id (вторая схема @Sam YC)
@Entity
public class Address implements Serializable {
@Id
@GeneratedValue
private String id;
private String city;
@OneToOne(optional = false)
@JoinColumn(name = "user_id", updatable = false)
private User user;
}
Вы используете @PrimaryKeyJoinColumn, когда хотите использовать первичный ключ ссылочного объекта, такой как первичный ключ целевого объекта. Здесь адрес знает ссылающегося пользователя, но в таблице адресов нет столбца внешнего ключа, потому что он имеет то же самоеid
чем User Id (первая схема @Sam YC)
@Entity
public class Address implements Serializable {
@Id
@GeneratedValue(generator = "foreignKeyGenerator")
@GenericGenerator(
name = "foreignKeyGenerator",
strategy = "foreign",
parameters = @org.hibernate.annotations.Parameter(
name = "property", value = "userT"
)
)
private String id;
private String city;
@OneToOne(optional = false)
@PrimaryKeyJoinColumn
private User userT;
}