Java 非主键列的一对一关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20041215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:36:06  来源:igfitidea点击:

OneToOne relationship for a non primary key column

javajakarta-eejpaone-to-onejoincolumn

提问by RDV

I'm having a problem when I query an entity who has a OneToOne relationship with another one. This is the scenario:

当我查询与另一个具有 OneToOne 关系的实体时,我遇到了问题。这是场景:

Database tables:

数据库表:

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

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

Test data:

测试数据:

insert into users (email) values ('[email protected]');
insert into users (email) values ('[email protected]');

insert into people (id, email) values (1, '[email protected]');
insert into people (id, email) values (2, '[email protected]');

Entities:

实体:

@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;
    }
}

Invocation:

调用:

...
User user = entityManager.find(User.class, "[email protected]");
...

After de invocation, the hibernate's logs shows:

取消调用后,休眠的日志显示:

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=?

As you can see, the join is wrong because is comparing users.email with people.id (user1_.email=person2_.id), so it returns an Userwithout its corresponding Person.

如您所见,连接是错误的,因为将 users.email 与 people.id ( user1_.email=person2_.id)进行比较,因此它返回一个没有其对应PersonUser

Any ideas about how can I fix it?

关于如何修复它的任何想法?

Thanks a lot !!

非常感谢 !!

采纳答案by Alan Hay

I think you should rethink your datamodel. The relationship between User and Person looks more like one of Inheritance.

我认为您应该重新考虑您的数据模型。User 和 Person 之间的关系看起来更像是一种继承关系。

For the issue with your mappings as they stand see here for some further disussion:

对于您的映射问题,请参见此处进一步讨论:

JPA providers: why do relationships/FKs to non-PK columns work in Hibernate and EclipseLink?

JPA 提供者:为什么与非 PK 列的关系/FK 在 Hibernate 和 EclipseLink 中有效?

Does the JPA specification allow references to non-primary key columns?

JPA 规范是否允许引用非主键列?

回答by Tom Anderson

Strictly speaking, the JPA specification does not allow references to non-primary key columns. It may work in some JPA implementations, but it's not proper.

严格来说,JPA 规范不允许引用非主键列。它可能适用于某些 JPA 实现,但并不合适。

However, i think you can do this by making the relationship bidirectional, and owned by the side with the non-primary key:

但是,我认为您可以通过使关系双向并由具有非主键的一方拥有来做到这一点:

@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;

}

I haven't actually tried that, though, so caveat hackor.

不过,我还没有真正尝试过,所以请注意 hackor