Рефакторинг ссылок JPA - PullRequest
       10

Рефакторинг ссылок JPA

2 голосов
/ 31 августа 2009

Я реорганизую некоторые классы из стандартного SQL в JPA / ORM. В большинстве случаев у Объектов есть «реальная» ссылка, но иногда ссылки на другие объекты даются только непроверенной ссылкой на идентификатор базы данных (без внешнего ключа, просто простая строка со ссылкой на другой идентификатор таблицы).

Код выглядит так:

@Entity
public final class myEntity implements Serializable {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "ID")
    private String id;

    @OneToOne
    @JoinColumn(name = "OBJREF", nullable = false)
    private otherObject objReference; /* Nice object reference */

    @Column(name = "OTHEROBJREF")
    private String otherObjReference; /* Damn db reference used by legacy code */
}

Как я должен иметь дело с otherObjReference? Атрибут используется устаревшими системами, которым требуется статическая конструкция getter / setter со строкой String! Если я останусь с идентификатором, у меня возникнут проблемы с запросами JPA, и я не смогу просто назначить объект и сохранить его.

Я думал о том, чтобы сделать String кратковременным и работать с @PrePersist и @PreLoad для загрузки «реальной» ссылки на объект, чтобы я мог работать с обоими. Но в этих методах у меня нет доступа к EntityManager (и постоянство не должно быть задачей этого pojo в этом случае ... это пахнет плохим дизайном, если я загружу ссылки здесь).

Поскольку "otherObjReference" является приватным, я также могу использовать методы получения и установки для загрузки данных из моей реальной ссылки. Но другие слои работают с объектами, поэтому они завершатся с ошибкой при вызове метода getOtherObjReference (), поскольку у них нет соединения с БД для загрузки объекта.

Ответы [ 2 ]

2 голосов
/ 01 сентября 2009

Также возможно (по крайней мере, с помощью toplink) сопоставить один и тот же столбец с двумя полями, если только одно можно обновлять и вставлять.

@Column(name = "OBJREF", nullable = false)
private String otherObjectId;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "OBJREF", nullable=false, updatable=false, insertable=false)
private OtherObject otherObject;

В вашем методе setOtherObject вы также можете установить otherObjectId. Единственная проблема с этим подходом состоит в том, что если вы установите только поле String, объект будет обновляться только при сохранении и перезагрузке сущности из базы данных.

1 голос
/ 31 августа 2009

Вы действительно пробовали свое последнее решение?

т.е. сделать обычное отображение JPA, а затем заставить получатель вернуть идентификатор, как это?

public ID getOtherObjId() {
  return otherObj.getId();
}

На самом деле, есть большая вероятность, что это сработает даже после того, как вы выйдете за границы сеанса. Я не уверен, как это работает сегодня, но, по крайней мере, в какой-то более старой версии hibernate он поместит ленивый прокси в ссылку otherObj, когда загрузит вашу сущность, и этот ленивый прокси будет содержать идентификатор ссылочного объекта. Поэтому, когда вы обращаетесь только к идентификатору otherObj, он будет достаточно умен, чтобы не загружать объект.

Если это не работает, вы всегда можете принудительно загрузить objectRef. Это немного дорого, но, возможно, оно того стоит.

(Кстати, если вы используете @OneToOne и nullable = true, он всегда будет загружать другую сторону с нетерпением. См. здесь (ищите «один к одному») для краткого объяснения)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...