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 а также определить BasicId отображение для столбца внешнего ключа.

Теперь возникает вопрос: являются ли @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;
}
Другие вопросы по тегам