如何实现复合键,让我们为参与事件的用户提供一个非常简单的示例,三个数据库表:User,Event,Users_Attending_Events这最后一个表有三个列:userID,eventID;它们与另外两个表的相应ID和成功相关联,这决定了用户是否参加了活动。
我希望参加一个单独的课程,并且不要直接加入用户和活动,因为出席会议包含"成功"信息,必须单独管理。
我的实施
用户对象:
@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 ...
}
参加课程:
@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类,用于复合键:
@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])
我错过了什么?
答案 0 :(得分:1)
<强>问题:强>
Exception非常直截了当地说映射的外键不是预期的类型,而你的问题是你试图在@ManyToOne
类型的属性中映射Integer
关系。错误的部分在这里。
<强>解决方案:强>
@ManyToOne
注释应引用您案例Entity
和User
中的映射Event
,而不是原始类型或实体的主键。
但是要定义Embeddable
主键,您可以在此处选择两个选项:
Embeddable
类中的属性。您的代码将是:
@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 ...
}
@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,并清楚地解释映射复合主键的所有可能情况。
重新阅读你的问题后,更好地关注问题,并从设计的角度思考问题,我认为用 a {{1}可以更好地说明你的情况ManyToMany
和User
实体之间的关系,加入表Event
具有额外列Attending
,它将更好地处理您的情况并解决问题。< / p>
我建议你看看这个Hibernate Many-to-Many Association with Extra Columns in Join Table Example tutorial它显示了一个类似的success
解决方案。