【问题标题】:Mapping keys in JPA: Primary key is a foreign keyJPA中的映射键:主键是外键
【发布时间】:2014-01-30 09:17:29
【问题描述】:

假设你有一个如下表:

CREATE TABLE IF NOT EXISTS CREDENTIAL (
    USER_NAME       VARCHAR(20) NOT NULL,
    HASHED_PASSWORD VARCHAR(128) NOT NULL,
    CREATION_DATE       TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    LAST_UPDATE_DATE    TIMESTAMP,
    LAST_UPDATED_BY VARCHAR(20),

    PRIMARY KEY (USER_NAME),
    FOREIGN KEY (USER_NAME) REFERENCES USER(USER_NAME),
    FOREIGN KEY (LAST_UPDATED_BY) REFERENCES USER(USER_NAME)
) CHARACTER SET utf8;

可以看到USER_NAME 列是表的主键和外键。是的,MySQL 成功生成了这张表。

问题很简单,我将如何在 JPA Entity 中映射它?我是否应该有 1 个 id 映射到 USER_NAME 列和另一个字段 User user 加入 USER_NAME 列?欢迎提出建议。

【问题讨论】:

    标签: java jpa jpa-2.0


    【解决方案1】:

    简单的解决方案是:

    @Entity
    public class Credential {
    
        @Id
        private String userName;
    
        @ManyToOne
        @JoinColumn(name = "user_name")
        private User owner;
    
        @ManyToOne
        @JoinColumn(name = "last_modified_by")
        private User lastUpdatedBy;
    
    
    }
    

    亲身经历:

    我建议创建一个数字类型的surrogate primary key(从数据库的角度来看是有益的)。您可以通过 DB 约束强制用户名的唯一性。

    【讨论】:

    • 为什么使用@ManyToOne?一个用户有一个凭证,因此USER_NAME 是主键。
    • ManyToOne 更容易使用。确实,您可以使用 OneToOne,但我发现 OneToOne 更难管理。此外,如果应用程序有多种验证用户的方式怎么办?
    • 有,但是其他认证方案是通过各自的3rd方认证完成的,所以不需要映射到@ManyToOne方案。
    • 好吧,在这种情况下,我建议不要为凭据引入单独的实体。只需将字段放入 User 类中。这将使事情变得非常美好和简单
    • @Funtik 可以通过引入 OneToOne 关系(数据库性能(检索的数据较少)、模块隔离)来解决多个问题,但这不是他的问题。您的解决方案不完整,我试图提供额外的提示。
    猜你喜欢
    • 2015-02-03
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2021-07-01
    • 1970-01-01
    • 2017-01-30
    • 2019-09-13
    相关资源
    最近更新 更多