Компонентный первичный ключ, внешний ключ. Ссылка на объект или ключ?
У меня есть два класса Foo
и Bar
. Таблицы в базе данных выглядят следующим образом:
|Foo|
|id : INT (PK) | bar_id : INT (PK, FK) |
|Bar|
|id : INT (PK) |
Обычно я бы отображал его следующим образом:
@Entity
public class Bar
{
@Id
@Column(name = "id")
private int id;
@OneToMany
private Set<Foo> foo;
}
@Entity
public class Foo
{
@EmbeddedId
private FooPK key;
@MapsId("barId")
@ManyToOne
@JoinColumn(name = "bar_id", referencedColumnName = "id")
private Bar bar;
}
@Embeddable
public class FooPK
{
@Column(name = "id")
private int id;
@Column(name = "bar_id")
private int barId;
}
Однако идентификатор в FooPK
слабо сопоставляется и должен быть подключен вручную. Я бы предпочел решение, которое отображает использование объектов вместо свободных идентификаторов.
Я пробовал следующее, но (конечно) это не сработало, но я думаю, что это дает представление о том, чего я хотел бы достичь:
@Entity
public class Bar
{
@Id
@Column(name = "id")
private int id;
@OneToMany
private Set<Foo> foo;
}
@Entity
public class Foo
{
@EmbeddedId
private FooPK key;
@MapsId("barId")
@ManyToOne
@JoinColumn(name = "bar_id", referencedColumnName = "id")
@Access(AccessType.FIELD)
private Bar getBar()
{
return key.getBar();
}
}
@Embeddable
public class FooPK
{
@Column(name = "id")
private int id;
@Transient
private Bar bar;
//....
@Column(name = "bar_id")
@Access(AccessType.PROPERTY)
private int getBarId
{
return bar.getId();
}
}
Другая проблема с последним решением заключается в том, что метод getBarId()
в FooPK
должен иметь метод setBarId(Int)
. Установка объекта с использованием идентификатора может быть выполнена путем доступа к уровню доступа к данным, однако это (на мой взгляд) нарушает разделение слоев бизнес/домен/данные.
Так что делать? Идите с первым решением и держите идентификаторы в синхронизации вручную или есть другая (лучшая) практика?
Ответы
Ответ 1
Ссылаясь на обсуждение JPA 2: составные классы первичных ключей, внесите следующие изменения в классы Foo и FooPK:
@Entity
public class Foo {
@EmbeddedId
private FooPK key;
@MapsId("barId") //references EmbeddedId property
@JoinColumn(name = "bar_id", referencedColumnName = "id")
@ManyToOne
private Bar bar;
}
@Embeddable
public class FooPK {
@Column(name = "id")
private int id;
@Column(name = "bar_id")
private int barId;
}
Я предлагаю сначала сделать его работу с доступом FIELD, а затем применить доступ к PROPERTY.
Так что делать? Пойдите с первым решением и сохраните идентификаторы в синхронизации вручную или есть другая (лучшая) практика?
Спасите себя от боли - автоматически создавайте идентификаторы.