Связь OneToOne для столбца, отличного от первичного ключа

StackOverflow https://stackoverflow.com//questions/20041215

Вопрос

У меня возникла проблема, когда я запрашиваю объект, у которого есть отношения OneToOne с другим объектом.Таков сценарий:

Таблицы базы данных:

create table people (
    id decimal(10,0) NOT NULL,
    email varchar(512) NOT NULL
);

create table users (
    email varchar(512) NOT NULL
);

Тестовые данные:

insert into users (email) values ('jhon@domain.com');
insert into users (email) values ('mary@domain.com');

insert into people (id, email) values (1, 'jhon@domain.com');
insert into people (id, email) values (2, 'mary@domain.com');

Сущности:

@Entity(name = "people")
public class Person implements Serializable {

    @Column
    @Id
    private long id;

    @Column
    private String email;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

@Entity(name = "tbl_users")
public class User implements Serializable {

    @Id
    private String email;

    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name = "email", referencedColumnName = "email")
    private Person person;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

Призыв:

...
User user = entityManager.find(User.class, "jhon@domain.com");
...

После отмены вызова в журналах гибернации отображается:

select user1_.email as email2_0_, person2_.id as id1_1_, person2_.email as email1_1_
from users user1_ left outer join people person2_ on user1_.email=person2_.id
where user1_.email=?

Как вы можете видеть, объединение неверно, потому что сравнивает users.email с people.id (user1_.email=person2_.id), таким образом, он возвращает Пользователь без соответствующего Человек.

Есть какие-нибудь идеи о том, как я могу это исправить?

Большое спасибо !!

Это было полезно?

Решение

Я думаю, вам следует переосмыслить свою модель данных.Отношения между Пользователем и Персоной больше похожи на отношения Наследования.

Что касается проблемы с вашими сопоставлениями в их нынешнем виде, смотрите здесь для дальнейшего обсуждения:

Поставщики JPA:почему отношения / FKS к столбцам, отличным от PK, работают в Hibernate и EclipseLink?

Разрешает ли спецификация JPA ссылки на столбцы, не являющиеся первичными ключами?

Другие советы

Строго говоря, спецификация JPA не допускает ссылок на столбцы, отличные от первичного ключа.Это может работать в некоторых реализациях JPA, но это неправильно.

Однако, я думаю, вы можете сделать это, сделав связь двунаправленной и принадлежащей стороне с непервичным ключом:

@Entity
public class Person {

    @Id
    private long id;

    @OneToOne
    @JoinColumn(name = "email")
    private User user;

    public String getEmail() {
        return user.getEmail();
    }

    public void setEmail(String email) {
        // left as an exercise for the reader
    }

}

@Entity
public class User {

    @Id
    private String email;

    @OneToOne(mappedBy = "user")
    private Person person;

}

Хотя на самом деле я этого не пробовал, так что предостережение от взлома.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top