b0x*_*0rz 18 java persistence annotations many-to-many primary-key
如何使表user_roles将两列(userID,roleID)定义为复合主键.应该很容易,只是记不住/找不到.
在user实体中:
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles")
public List<RoleDAO> getRoles() {
return roles;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getUserID() {
return userID;
}
Run Code Online (Sandbox Code Playgroud)
在roles实体中:
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles")
public List<UserDAO> getUsers() {
return users;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getRoleID() {
return roleID;
}
Run Code Online (Sandbox Code Playgroud)
谢谢.
**更多信息
因此,有一个第三表user_roles即花费(由上述自动生成)userID从user实体和roleID从roles实体.现在我需要生成的table(user_roles)中的这两列是一个复合主键.
Tim*_*Tim 22
你已经在这里找到了一些关于如何完全按照你的要求做出的好答案.
作为参考,我只想提一下在Hibernate中这样做的推荐方法,即使用代理键作为主键,并将业务键标记为NaturalId:
虽然我们建议使用代理键作为主键,但您应该尝试识别所有实体的自然键.自然键是属性或属性的组合,它们是唯一且非空的.它也是不可改变的.映射元素内的自然键的属性.Hibernate将生成必要的唯一键和可空性约束,因此,您的映射将更加自我记录.
建议您实现equals()和hashCode()以比较实体的自然键属性.
在代码中,使用注释,这看起来像这样:
@Entity
public class UserRole {
@Id
@GeneratedValue
private long id;
@NaturalId
private User user;
@NaturalId
private Role role;
}
Run Code Online (Sandbox Code Playgroud)
使用它可以为您节省很多麻烦,因为您会发现您经常需要引用/映射组合主键.
我发现这很困难,最后只是放弃了与Hibernate的斗争,而是决定顺其自然.我完全理解,在您的情况下这可能是不可能的,因为您可能正在处理遗留软件或依赖项,但我只是想提及它以供将来参考.(如果你不能使用它也许其他人可以!)
Art*_*ald 12
为了满足您的要求,您可以将@ManyToMany映射为@OneToMany映射.这样,USER_ROLE将包含USER_ID和ROLE_ID作为复合主键
我会告诉你如何:
@Entity
@Table(name="USER")
public class User {
@Id
@GeneratedValue
private Integer id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="joinedUserRoleId.user")
private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();
// no-arg required constructor
public User() {}
public User(Integer id) {
this.id = id;
}
// addRole sets up bidirectional relationship
public void addRole(Role role) {
// Notice a JoinedUserRole object
JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(this, role));
joinedUserRole.setUser(this);
joinedUserRole.setRole(role);
joinedUserRoleList.add(joinedUserRole);
}
}
@Entity
@Table(name="USER_ROLE")
public class JoinedUserRole {
public JoinedUserRole() {}
public JoinedUserRole(JoinedUserRoleId joinedUserRoleId) {
this.joinedUserRoleId = joinedUserRoleId;
}
@ManyToOne
@JoinColumn(name="USER_ID", insertable=false, updatable=false)
private User user;
@ManyToOne
@JoinColumn(name="ROLE_ID", insertable=false, updatable=false)
private Role role;
@EmbeddedId
// Implemented as static class - see bellow
private JoinedUserRoleId joinedUserRoleId;
// required because JoinedUserRole contains composite id
@Embeddable
public static class JoinedUserRoleId implements Serializable {
@ManyToOne
@JoinColumn(name="USER_ID")
private User user;
@ManyToOne
@JoinColumn(name="ROLE_ID")
private Role role;
// required no arg constructor
public JoinedUserRoleId() {}
public JoinedUserRoleId(User user, Role role) {
this.user = user;
this.role = role;
}
public JoinedUserRoleId(Integer userId, Integer roleId) {
this(new User(userId), new Role(roleId));
}
@Override
public boolean equals(Object instance) {
if (instance == null)
return false;
if (!(instance instanceof JoinedUserRoleId))
return false;
final JoinedUserRoleId other = (JoinedUserRoleId) instance;
if (!(user.getId().equals(other.getUser().getId())))
return false;
if (!(role.getId().equals(other.getRole().getId())))
return false;
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 47 * hash + (this.user != null ? this.user.hashCode() : 0);
hash = 47 * hash + (this.role != null ? this.role.hashCode() : 0);
return hash;
}
}
}
Run Code Online (Sandbox Code Playgroud)
记得
如果对象具有指定的标识符或复合键,则在调用save()之前,应该将标识符分配给对象实例.
所以我们创建了一个像这样的JoinedUserRoleId构造函数来处理它
public JoinedUserRoleId(User user, Role role) {
this.user = user;
this.role = role;
}
Run Code Online (Sandbox Code Playgroud)
最后是Role类
@Entity
@Table(name="ROLE")
public class Role {
@Id
@GeneratedValue
private Integer id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="JoinedUserRoleId.role")
private List<JoinedUserRole> joinedUserRoleList = new ArrayList<JoinedUserRole>();
// no-arg required constructor
public Role() {}
public Role(Integer id) {
this.id = id;
}
// addUser sets up bidirectional relationship
public void addUser(User user) {
// Notice a JoinedUserRole object
JoinedUserRole joinedUserRole = new JoinedUserRole(new JoinedUserRole.JoinedUserRoleId(user, this));
joinedUserRole.setUser(user);
joinedUserRole.setRole(this);
joinedUserRoleList.add(joinedUserRole);
}
}
Run Code Online (Sandbox Code Playgroud)
根据测试它,让我们写下面的内容
User user = new User();
Role role = new Role();
// code in order to save a User and a Role
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Serializable userId = session.save(user);
Serializable roleId = session.save(role);
session.getTransaction().commit();
session.clear();
session.close();
// code in order to set up bidirectional relationship
Session anotherSession = HibernateUtil.getSessionFactory().openSession();
anotherSession.beginTransaction();
User savedUser = (User) anotherSession.load(User.class, userId);
Role savedRole = (Role) anotherSession.load(Role.class, roleId);
// Automatic dirty checking
// It will set up bidirectional relationship
savedUser.addRole(savedRole);
anotherSession.getTransaction().commit();
anotherSession.clear();
anotherSession.close();
Run Code Online (Sandbox Code Playgroud)
请注意根据以上代码无参考JoinedUserRole类.
如果要检索JoinedUserRole,请尝试以下操作
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Integer userId;
Integer roleId;
// Lets say you have set up both userId and roleId
JoinedUserRole joinedUserRole = (JoinedUserRole) session.get(JoinedUserRole.class, new JoinedUserRole.JoinedUserRoleId(userId, roleId));
// some operations
session.getTransaction().commit();
session.clear();
session.close();
Run Code Online (Sandbox Code Playgroud)
问候,