【问题标题】:How do I map this composite primary key?如何映射此复合主键?
【发布时间】:2020-02-03 22:56:04
【问题描述】:

我正在使用 spring 创建一个社交媒体网站,但我遇到了复合主键的问题。 我有 User、Post 和 PostLike 表,我需要跟踪哪些用户喜欢哪些帖子。我还有一个 UserData 和 Post 关系,它告诉我帖子作者,但这不会造成任何问题。基本上,我的 PostLike 表应该包含 post_id 和 user_id 列,它们应该用作复合主键。

我试图通过创建一个可嵌入的 PostLikeId 来做到这一点:

我的 PostLikeId 类:

@Embeddable
public class PostLikeId implements Serializable {

    @Column(name = "post_id")
    private Post post;

    @Column(name = "user_id")
    private UserData user;

    // getters and setters

}

我的 PostLike 类:

@Entity
@Table(name = "post_like")
public class PostLike {

    @EmbeddedId
    private PostLikeId id;

    //getters and setters
}

我的帖子类:

@Entity
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "post_id_seq_generator")
    @SequenceGenerator(name = "post_id_seq_generator", sequenceName = "post_id_seq", allocationSize = 10)
    @Column(name = "id", updatable = false)
    private Long id;

    @OneToMany(cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    @JoinColumns({
            @JoinColumn(name = "post_id",
                    referencedColumnName = "post_id"),
            @JoinColumn(name = "user_id",
                    referencedColumnName = "user_id")
    })
    private List<PostLike> likes = new ArrayList<>();

}

...和我的 UserData 类:

@Entity
@Table(name = "user_data")
public class UserData {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_data_id_seq_generator")
    @SequenceGenerator(name = "user_data_id_seq_generator", sequenceName = "user_data_id_seq", allocationSize = 10)
    @Column(name = "id", updatable = false)
    private Long id;

    @OneToMany(
            mappedBy = "user",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Post> posts = new ArrayList<>();

    @OneToMany(
            mappedBy = "id",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<PostLike> likedPosts = new ArrayList<>();

当我尝试运行和映射它时,我得到以下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unable to map collection com.budano.SocialStudent.model.Post.likes
.
.
.
Caused by: org.hibernate.AnnotationException: Unable to map collection com.budano.SocialStudent.model.Post.likes
.
.
.
Caused by: org.hibernate.cfg.RecoverableException: Unable to find column with logical name: post_id in org.hibernate.mapping.Table(public.post) and its related supertables and secondary tables

谁能解释一下这个日志告诉我什么以及我应该如何解决这个问题? 谢谢!

【问题讨论】:

    标签: java spring postgresql hibernate jpa


    【解决方案1】:

    这是您可以尝试的方法:

    PostLikeId:

    @Embeddable
    public class PostLikeId implements Serializable {
    
        @Column(name = "post_id")
        private Long postId; // corresponds to PK type of Post
    
        @Column(name = "user_id")
        private Long userId; // corresponds to PK type of User
    
        // ...
    
    }
    

    点赞:

    @Entity
    @Table(name = "post_like")
    public class PostLike {
    
        @EmbeddedId
        private PostLikeId id;
    
        @MapsId("postId") // maps postId attribute of embedded id
        @ManyToOne
        private Post post;
    
        @MapsId("userId") // maps userId attribute of embedded id
        @ManyToOne
        private UserData user;
    
        // ...
    }
    

    帖子:

    @Entity
    @Table(name = "post")
    public class Post {
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "post_id_seq_generator")
        @SequenceGenerator(name = "post_id_seq_generator", sequenceName = "post_id_seq", allocationSize = 10)
        @Column(name = "id", updatable = false)
        private Long id;
    
        @ManyToOne
        private UserData user;
    
        @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
        private List<PostLike> likes = new ArrayList<>();
    
        // ...
    }
    

    用户数据:

    @Entity
    @Table(name = "user_data")
    public class UserData {
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_data_id_seq_generator")
        @SequenceGenerator(name = "user_data_id_seq_generator", sequenceName = "user_data_id_seq", allocationSize = 10)
        @Column(name = "id", updatable = false)
        private Long id;
    
        @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
        private List<Post> posts = new ArrayList<>();
    
        @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
        private List<PostLike> likedPosts = new ArrayList<>();
    
        // ...
    }
    

    在第 2.4.1 节的JPA 2.2 spec 中讨论了派生的身份(带有示例)。

    【讨论】:

    • 非常感谢!奇迹般有效。我想我现在掌握了复合键的工作原理。
    猜你喜欢
    • 2019-04-22
    • 2018-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 2017-01-30
    • 2020-10-04
    • 1970-01-01
    相关资源
    最近更新 更多