Hibernate 中的 Composite ID 如何映射 Key class

Composite ID in Hibernate how to map Key class

如何实现复合键,让我们做一个非常简单的示例用户参加活动,三个数据库 tables:用户,事件,Users_Attending_Events 最后一个 table 有三个列:用户ID,事件ID;它们与另外两个 table 和 success 的各自 ID 相结合,这决定了用户是否向事件炫耀。

我希望 Attenting 是一个单独的 class,不要直接加入 User 和 Event,因为 Attenting 包含 "success" 信息,必须单独管理。

我的实现

用户对象:

@Entity
@Table(name = "[users]")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer userID;
    @JsonIgnore
    @OneToMany(mappedBy = "attend", targetEntity = Attending.class, fetch = FetchType.LAZY)
    private Set<Attending> attendEvents = new HashSet<Attending>();
...
// setters, getters, constructors, equal and hash ...
}

事件:

@Entity
@Table(name = "events")
public class Event implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer eventID;
    @JsonIgnore
    @OneToMany(mappedBy = "attend", targetEntity = Attending.class, fetch = FetchType.LAZY)
    private Set<Attending> participants = new HashSet<Attending>();
...
// setters, getters, constructors, equal and hash ...
}

参加 class:

@Entity
@Table(name = "users_attending_events")
public class Attending implements Serializable {

        @EmbeddedId
        protected AttendingID attend;

        private Integer success;
    ...
    // setters, getters, constructors, equal and hash ...
    }

AttendingID class,复合键:

  @Embeddable
  public class AttendingID implements Serializable {

        @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
        @JoinColumn(name = "users_userID", referencedColumnName = "userID")
        private Integer user;

        @ManyToOne(targetEntity = Event.class, fetch = FetchType.LAZY)
        @JoinColumn(name = "events_eventID", referencedColumnName = "eventID")
        private Integer event;
    ...
    // setters, getters, constructors, equal and hash ...
    }

虽然 运行 我遇到异常:

org.hibernate.MappingException: Foreign key (FKlerh9fv4q1rjiusg0ful3m15j:users_attending_events [events_eventID,users_userID])) must have same number of columns as the referenced primary key (users [userID])

我错过了什么?

问题:

异常非常简单,说明映射的外键不是预期的类型,你的问题是你试图在 Integer 类型的属性中映射 @ManyToOne 关系这里是错误的部分。

解法:

@ManyToOne 注释应引用映射 Entity 在您的情况下 UserEvent 而不是原始类型或实体的主键。

但是要定义 Embeddable 主键,您在这里有两个选择:

  1. 在您的 Embeddable class.
  2. 中仅使用映射实体主键作为属性

您的代码将是:

@Embeddable
public class AttendingID implements Serializable {

    @Column(name = "users_userID")
    private Integer userID;

    @Column(name = "events_eventID")
    private Integer eventID;

    ...
    // setters, getters, constructors, equal and hash ...
}
  1. 或者将两个映射实体用作可嵌入主键中的属性,并使用 @ManyToOne 注释引用它们。

因此在您的代码中,您只需要更改 user

的类型
@Embeddable
public class AttendingID implements Serializable {

    @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "users_userID", referencedColumnName = "userID")
    private User user;

    @ManyToOne(targetEntity = Event.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "events_eventID", referencedColumnName = "eventID")
    private Event event;

    ...
    // setters, getters, constructors, equal and hash ...
}

文档:

如需进一步阅读和更多选项,您可以查看 5.1.2.1. Composite identifier Section in Hibernate Mapping Documentation 它显示并清楚地解释了映射复合主键的所有可能情况。


编辑:

在重新阅读你的问题后,更好地关注问题并从 vue 的设计角度思考它,我认为你的情况可以更好地说明 UserEvent 实体之间的 ManyToMany 关系,具有 Join Table Attending 和 Extra 列 success,它将更好地处理您的情况并解决问题。

我建议你看看这个 Hibernate Many-to-Many Association with Extra Columns in Join Table Example tutorial 它显示了一个类似的 ManyToMany 解决方案。