Hibernate - внешние ключи вместо сущностей - PullRequest
45 голосов
/ 11 июня 2011

В настоящее время Hibernate позволяет загружать объекты, определенные отношениями *-to-one, непосредственно с

entity1.getEntity2()

Возможно ли получить внешний ключ вместо объекта?

текущий подход, который я вижу, имеет добавление к моему отображению:

@JoinColumn(name="message_key")
@ManyToOne(targetEntity=Message.class,fetch=FetchType.LAZY)
private Message message;  //these lines currently exist

@Column(name="message_key")
private Long message_fk; //the idea is to add those 2 lines

Есть ли лучший подход для получения внешнего ключа или это единственный?

Ответы [ 4 ]

44 голосов
/ 11 июня 2011

Да, вы можете сделать это. Вам просто нужно прояснить для hibernate, какой из них является отображением, которое он должен поддерживать, например так:

@Column(name="message_key", updatable=false, insertable=false)
private Long message_fk;
15 голосов
/ 11 июня 2011

Если вам все еще нужна ссылка на вашу сущность, но вы не хотите загружать ее из базы данных просто для того, чтобы получить внешний ключ, ваш подход правильный.Добавьте вставляемый и Updatabale = false в атрибут Column, чтобы предотвратить потерю правильной ссылки на сущность.

@JoinColumn(name = "message_key")
@ManyToOne(targetEntity = Messages.class, fetch = FetchType.LAZY)
private Messages message;

@Column(name = "message_key", insertable = false, updatable = false)
private Long message_fk;
4 голосов
/ 26 сентября 2012

На самом деле, поведение Hibernate по умолчанию загружает только внешний ключ вместо объекта сообщения, если FetchType имеет тип LAZY. Вот почему при указании LAZY FetchType существуют прокси-объекты для загружаемых объектов.

Внешний ключ не виден напрямую, но он, конечно, является ключом объекта в конце «one» отношения OneToMany.

Однако с типом доступа на основе полей (например, в вашем случае, когда аннотации размещаются на полях), существует нерешенная проблема гибернации: Hibernate загружает весь объект за прокси-сервером из базы данных. (http://blog.xebia.com/2009/06/13/jpa-implementation-patterns-field-access-vs-property-access/)

Мое конкретное предложение было бы (как, например, «правильный» ответ не работал в моем случае):

  • Используйте объект сообщения напрямую, так как Hibernate загрузит его, только если нужны данные без внешнего ключа. Не указывайте дополнительное поле для внешнего ключа.
  • Переключите класс для использования доступа к свойству, то есть определите получатели и установщики и поместите ваши аннотации из полей в получатели.
1 голос
/ 11 июня 2011
Long fk = entity1.getEntity2().getId();

Это должно работать. Это не сработает, только если у вас есть составные первичные ключи, на которые ссылаются как на внешние ключи, но ваше решение также не сработает в этом случае. Учитывая мое решение, даже составной ключ не будет выглядеть так безобразно.

Long fkField1 = entity1.getEntity2().getCol1();
String fkField2 = entity1.getEntity2().getCol2();

Нечто подобное будет работать.

EDIT: Если больше думать о предложенном решении, оно все равно не сработает, поскольку Hibernate уже пытается автоматически создать поле FK для отношения Mapped, поэтому при определении другого @Column просто попытается выполнить привязку ко второму столбцу с тем же именем.

...