【问题标题】:OneToOne relationship for a non primary key column非主键列的 OneToOne 关系
【发布时间】:2013-11-18 06:11:23
【问题描述】:

我在查询与另一个实体具有 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");
...

de调用后,hibernate的日志显示:

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),所以它返回一个 User 没有对应的Person

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

非常感谢!!

【问题讨论】:

    标签: java jakarta-ee jpa one-to-one joincolumn


    【解决方案1】:

    严格来说,the JPA specification does not allow references to non-primary key columns。它可能在某些 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;
    
    }
    

    不过,我实际上并没有尝试过,所以 caveat hackor

    【讨论】:

    • @OneToOne 属性上不允许使用@Column:
    • @Robbo_UK 好点,谢谢。应该是@JoinColumn,对吧?我已经改了。
    • 您必须设置一个迷你项目并对其进行测试。我在尝试使用非 PK 字段引用表时遇到了问题。
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2015-03-10
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 2014-01-21
      • 2015-03-25
      相关资源
      最近更新 更多