Итак, ситуация такова: существует сущность, которая должна быть связана со словарем. Представьте себе следующую структуру
create table Address (
addressId bigint not null,
addressLine1 varchar(255),
city varchar(255),
country varchar(255),
state varchar(255),
zipCode varchar(255),
primary key (addressId)
)
create table STATES_DICT (
state_code varchar(255),
state_fullname varchar(255),
primary key (state_code)
)
Я хочу отобразить и ADDRESS, и STATE_DICTIONARY в одну сущность.
@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {
@Id
@Column(name = "ADDRESSID")
private int addressId;
@Column(name = "ADDRESSLINE1")
private String addressLine1;
@Column(name = "STATE")
private String state;
//??? annotations
private String fullStateName;
@Column(name = "ZIPCODE")
private String zipCode;
@Column(name = "CITY")
private String city;
@Column(name = "COUNTRY")
private String country;
//... getters and setters
}
Для чистого SQL я буду запускать
select a.ADDRESSID, a.ADDRESSLINE1, a.CITY, a.ZIPCODE, a.STATE,
d.STATE_FULLNAME, a.COUNTRY
from ADDRESS a, STATES_DICT d where a.STATE = d.STATE_CODE
но у меня серьезные проблемы с отображением с помощью JPA.
- Я не могу использовать @SecondaryTable, поскольку таблицы не отображаются первичными ключами
- Лучшее, что я мог получить:
@ElementCollection
@JoinTable(name="STATES_DICT",
joinColumns=@JoinColumn(name="STATE_CODE", referencedColumnName="STATE"))
@Column(name = "STATE_FULLNAME")
private Collection<String> fullStateName;
Недостатком является то, что отображение всегда один-к-одному, а Коллекция вносит путаницу, и отношение больше один-к-одному (многие-к-одному), а не один-ко-многим.
Есть идеи? Есть ли эквивалент @ElementCollection для однозначных сопоставлений?
Удаление @ElementCollection не помогает. Ожидается, что поле fullStateName будет находиться в столбце ADDRESS - это не так.
Некоторые заметки:
* Мне нужно, чтобы эти двое были вместе в одной сущности.
* Я расширяю существующее решение, нужно добавить только этот столбец словаря
* Объект обрабатывается позже другим сервисом, который работает только через примитивные типы. Я бы не стал менять службу, поэтому добавление отношения @OneToOne нежелательно
Большое спасибо
Я расширяю вопрос с примером @SecondaryTable, который мне не помог.
@Entity
@Table(name = "ADDRESS")
@SecondaryTable(name="STATES_DICT",
pkJoinColumns=@PrimaryKeyJoinColumn(columnDefinition="STATE_CODE", referencedColumnName="STATE"))
public class Address implements Serializable {
@Id
@Column(name = "ADDRESSID")
private int addressId;
@Column(name = "ADDRESSLINE1")
private String addressLine1;
@Column(name = "STATE")
private String state;
@Column(table="STATES_DICT", name = "STATE_FULLNAME")
private String fullStateName;
@Column(name = "ZIPCODE")
private String zipCode;
@Column(name = "CITY")
private String city;
@Column(name = "COUNTRY")
private String country;
//... getters and setters
}
Это вызвало неприятное исключение:
Вызывается: org.hibernate.AnnotationException: SecondaryTable JoinColumn не может ссылаться на не первичный ключ
Для протокола - я не смог найти способ сделать это (и предположил, что это просто не тот способ, которым это должно быть сделано). Я пошел с аннотациями отношений (@ManyToOne, @OneToOne) и @JoinColumn - так что правильный путь. Я настроил логику дальнейшей обработки для обработки аннотаций @JoinColumn так же, как она работает с @Column. Это сработало.
Дальнейшая обработка - это функция безопасности, которая подавляет значения на основе пользовательских ролей и исходных имен столбцов базы данных. Вот почему для меня было так важно придерживаться аннотации @Column