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
在您的情况下 User
和 Event
而不是原始类型或实体的主键。
但是要定义 Embeddable
主键,您在这里有两个选择:
- 在您的
Embeddable
class. 中仅使用映射实体主键作为属性
您的代码将是:
@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 它显示并清楚地解释了映射复合主键的所有可能情况。
编辑:
在重新阅读你的问题后,更好地关注问题并从 vue 的设计角度思考它,我认为你的情况可以更好地说明 User
和 Event
实体之间的 ManyToMany
关系,具有 Join Table Attending
和 Extra 列 success
,它将更好地处理您的情况并解决问题。
我建议你看看这个 Hibernate Many-to-Many Association with Extra Columns in Join Table Example tutorial 它显示了一个类似的 ManyToMany
解决方案。
如何实现复合键,让我们做一个非常简单的示例用户参加活动,三个数据库 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
在您的情况下 User
和 Event
而不是原始类型或实体的主键。
但是要定义 Embeddable
主键,您在这里有两个选择:
- 在您的
Embeddable
class. 中仅使用映射实体主键作为属性
您的代码将是:
@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 它显示并清楚地解释了映射复合主键的所有可能情况。
编辑:
在重新阅读你的问题后,更好地关注问题并从 vue 的设计角度思考它,我认为你的情况可以更好地说明 User
和 Event
实体之间的 ManyToMany
关系,具有 Join Table Attending
和 Extra 列 success
,它将更好地处理您的情况并解决问题。
我建议你看看这个 Hibernate Many-to-Many Association with Extra Columns in Join Table Example tutorial 它显示了一个类似的 ManyToMany
解决方案。