Индивидуальные сопоставления базового типа в одном классе в Hibernate - PullRequest
5 голосов
/ 05 октября 2011

Итак, ситуация такова: существует сущность, которая должна быть связана со словарем. Представьте себе следующую структуру

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.

  1. Я не могу использовать @SecondaryTable, поскольку таблицы не отображаются первичными ключами
  2. Лучшее, что я мог получить:
    @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

Ответы [ 3 ]

1 голос
/ 28 марта 2014

Ответ от пользователя2601805 правильный с использованием

@PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")

В вашем случае этого должно быть достаточно, поскольку все, что вам нужно, - это свойство из STATES_DICT.

Я также задал вопрос, касающийся JPA, чтопоказан пример использования @SecondaryTable и @Embeddable для достижения чего-то похожего на @ElementCollection, но для @ OneToOne

Также см. этот блог, например http://www.bagdemir.com/2013/03/03/mapping-embeddable-objects-whichve-no-identities-using-multiple-tables-with-jpahibernate/

0 голосов
/ 20 июля 2013

В @pkJoinColumns вы должны использовать:

@PrimaryKeyJoinColumn(name="STATE_CODE", referencedColumnName="STATE")

У меня та же проблема, и ваш намек на использование @SecondaryTable решил мою проблему.См. Отображение одного объекта в несколько таблиц для получения дополнительной информации.

0 голосов
/ 05 октября 2011

Вы должны быть в состоянии создать класс @Embeddable State, который отображает связь, но предоставляет метод делегата для представления имени состояния как свойства. Будет ли это сделать то, что вы пытаетесь сделать?

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