【问题标题】:JPA make a part of the composite foreign key part of primary keyJPA使复合外键的一部分成为主键的一部分
【发布时间】:2021-02-09 19:45:44
【问题描述】:

我查看了所有可能的 Google 搜索和 Stackoverflow 搜索,但找不到我要查找的内容。我的问题是有一个 A 类和一个 B 类,A 类有一个复合主键,B 类有一个原始主键。这些类(表)与一个名为 C 的类连接,我需要这个,因为连接中还有其他数据(底部的示例)。在 C 类中,我显然将 B 类和 A 类的主键作为外键,但是我需要 B 类的复合键和 A 的外键的第一个属性作为 C 类的主键。

仅用文字有点难以理解,所以这里是示例:

public class CompositeId implements Serializable {
    private Long id;

    private Long version;

    // Other stuff...
}

@Entity
@IdClass(CompositeId.class)
public class A {
    @Id
    private Long id;

    @Id
    private Long version;

    private String name;

    private String creatorName;

    // Other stuff...
}

@Entity
public class B {
    private Long id;

    private String name;

    // Othet stuff...
}

public class CompositeJoinId implements Serializable {
    private Long aId; // Should equal to aReference's id property.

    private Long bId; // Should equal to bReference's id property.

    // Other stuff...
}

@IdClass(CompositeJoinId.class)
@Entity
public class C {
    @Id
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="a_id", referencedColumnName="id"),
        @JoinColumn(name="a_version", referencedColumnName="version")
    })
    private A aReference;

    @Id
    @ManyToOne
    @JoinColumn(name = "b_id")
    private B bReference;

    private Long day;

    // Other stuff...
}

有没有办法做到这一点?我所有的发现只使用一个使用两个外键的类,但我只需要/想要一个。

【问题讨论】:

    标签: mysql hibernate jpa


    【解决方案1】:

    我不完全确定我是否理解您的问题;但我会像这样映射你的类(主要区别是CompositeJoinId):

    public class CompositeId implements Serializable {
        private Long id;
    
        private Long version;
    
        // Other stuff...
    }
    
    @Entity
    @IdClass(CompositeId.class)
    public class A {
        @Id
        private Long id;
    
        @Id
        private Long version;
    
        private String name;
    
        private String creatorName;
    
        // Other stuff...
    }
    
    @Entity
    public class B {
        @Id
        private Long id;
    
        private String name;
    
        // Othet stuff...
    }
    
    public class CompositeJoinId implements Serializable {
        private Long aId;
    
        private Long bReference; // matches name of @Id attribute and type of B PK
    
        // Other stuff...
    }
    
    @IdClass(CompositeJoinId.class)
    @Entity
    public class C {
        @Id
        @Column(name = "a_id", insertable = false, updatable = false)
        Long aId;
    
        @Id
        @ManyToOne
        @JoinColumn(name = "b_id")
        private B bReference;
    
        @ManyToOne
        @JoinColumns({
            @JoinColumn(name="a_id", referencedColumnName="id"),
            @JoinColumn(name="a_version", referencedColumnName="version")
        })
        private A aReference;
    
        private Long day;
    
        // Other stuff...
    }
    

    这些是派生身份的示例;和派生的身份在第 2.4.1 节的JPA 2.2 spec 中讨论(带有示例)。

    【讨论】:

    • 这样我在 C 类中的主键将是 A.id、A.version 和 B.id,我只需要/想要 A.id 和 B.id。这就是为什么我只使用复合连接 id 类中的 id。所以不幸的是,这对我不起作用。
    • 即使您不需要/想要A.id,您仍然可以告诉 JPA 将其用作 C 的 id 的一部分;因为 JPA 仍然可以使用它来唯一标识 C 实例。除非您使用 JPA 映射来生成 DDL(这是不明智的 :-),否则这些映射应该没有问题。它们在您使用时会引起任何问题吗?
    • 就是这样,我不想编写自己的数据库脚本,因为那样我就可以使用普通的 JDBC...所以是的,我正在从这些模型生成我的数据库,这就是我为什么卡住。您还有其他方法可以做到这一点吗?如果我自己编写我的 sql 脚本并指定 C 类的主键是 A.id 和 B.id 那么 JPA 会做什么?
    • 如果您认为 JPA 只是提供了一种生成数据库的方法,那么您就严重低估了 JPA。但你并不孤单...... :-( 无论如何:你可以尝试将只读字段映射到适当的列。我会改变我的答案以反映可能有用的东西。
    • 我知道它可以做我什至不知道的事情,但目前我不需要这些功能。我只需要从模型中正确生成数据库,感谢您的编辑,我将不迟于明天检查它。再次感谢。
    猜你喜欢
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2015-12-14
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多