8

我有一个非常标准的场景,其中我有一个以 user_id 作为 PK 的用户表和一个以 role_id 作为 PK 的角色表。这两个表通过多对多关系相关(即,用户可以有多个角色,一个角色可以应用于多个用户),随后我有一个名为 users_has_roles 的连接表。users_has_roles 中仅有的两列是 users_user_id 和 roles_role_id。

我已经生成了实体类(见下文),并且将数据持久保存到用户和角色表中没有问题,但是我失败了,将任何内容持久保存到 users_has_roles 加入表中,因此目前我的用户都没有被分配角色。在我发疯之前,有人可以让我摆脱痛苦并告诉我应该如何将带有相应角色角色标识的 users_user_id 添加到 users_has_roles 表中,以便我的用户可以拥有角色吗?

我的 Users.java 实体类:

@Entity
@Table(name = "users")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
@NamedQuery(name = "Users.findByUserId", query = "SELECT u FROM Users u WHERE u.userId = :userId"),
@NamedQuery(name = "Users.findByUsername", query = "SELECT u FROM Users u WHERE u.username = :username"),
@NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")})
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 60)
@Column(name = "user_id")
private String userId;
@Basic(optional = false)
@NotNull
@Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")
@Size(min = 1, max = 45)
@Column(name = "username")
private String username;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 120)
@Column(name = "password")
private String password;
@JoinTable(name = "users_has_roles", joinColumns = {
    @JoinColumn(name = "users_user_id", referencedColumnName = "user_id")}, inverseJoinColumns = {
    @JoinColumn(name = "roles_role_id", referencedColumnName = "role_id")})
@ManyToMany
private Collection<Roles> rolesCollection;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usersUserId")
private Collection<UserAccount> userAccountCollection;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usersUserId")
private Collection<UserDetails> userDetailsCollection;

...

All the getter and setter methods etc.

我的 Roles.java 实体类:

@Entity
@Table(name = "roles")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Roles.findAll", query = "SELECT r FROM Roles r"),
@NamedQuery(name = "Roles.findByRoleId", query = "SELECT r FROM Roles r WHERE r.roleId = :roleId"),
@NamedQuery(name = "Roles.findByRoleName", query = "SELECT r FROM Roles r WHERE r.roleName = :roleName"),
@NamedQuery(name = "Roles.findByRolePermission", query = "SELECT r FROM Roles r WHERE r.rolePermission = :rolePermission"),
@NamedQuery(name = "Roles.findByRoleDescription", query = "SELECT r FROM Roles r WHERE r.roleDescription = :roleDescription")})
public class Roles implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 60)
@Column(name = "role_id")
private String roleId;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 45)
@Column(name = "role_name")
private String roleName;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 45)
@Column(name = "role_permission")
private String rolePermission;
@Size(max = 45)
@Column(name = "role_description")
private String roleDescription;
@ManyToMany(mappedBy = "rolesCollection")
private Collection<Users> usersCollection;

...

All the getter and setter methods etc.

谢谢

- - 更新 - -

// New Users
Users currentUser = new Users();
currentUser.setUserId(userId);
currentUser.setUsername(email);
currentUser.setPassword(password);
getUsersFacade().create(currentUser);
4

2 回答 2

9

好的,首先感谢 Mikko 引导我找到答案。我只是想发布一个可能对可能处于我所处位置的任何其他人直接有帮助的答案。这也是基于 Eureka 时刻,所以它在技术上可能不正确,但这就是我的看法。

我面临的一个大问题是,在 MySQL 中,我可以将桥接表视为一个单独的表!(抱歉,我无法发布我的 EER 图的图像,但我目前似乎没有足够的权限)所以我假设 Java 也会将桥接表视为一个表!好吧,它没有。该桥接表在 Java 中并不像传统表那样真正存在,它实际上由与之关联的相对表集合类型表示。

对我来说,最简单的查看方法是完全忘记桥接表并专注于两个“真实”表并将其中的数据关联起来。以下代码不是最佳实践,因为我只是设置了 role_id,但这只是为了表明我的观点。

List<Roles> userRoleList = new ArrayList<Roles>();

Users currentUser = new Users();
currentUser.setUserId(userId);
currentUser.setUsername(email);
currentUser.setPassword(password);

Roles userRole = new Roles();
userRole.setRoleId("2");

userRoleList.add(userRole);
currentUser.setRolesCollection(userRoleList);

getUsersFacade().create(currentUser);

希望这可以帮助其他在多对多关系中苦苦挣扎的人。

(注意。为了方便起见,我编辑了原始问题代码以使用 List 而不是 Collection,但您也可以使用任何其他适合您需要的类型。)

于 2012-04-22T16:55:17.550 回答
6

您的示例工作正常(EclipseLink 2.3,MySQL)。可能的问题在于您未显示的部分代码。例如在将元素添加到角色集合中。典型的错误是例如仅将元素添加到非拥有方。

为了持久化它,你必须关心拥有方的关系(没有mappedBy),为了保持内存中的对象图与数据库一致,你应该始终修改关系的双方。

我尝试了以下方法:

    // method to add element to rolesCollection
    public void addRoles(Roles r) {
        rolesCollection.add(r);
    }

    //first created new instances of Users and Roles
    // then:
    tx.begin();
    users.addRoles(r);
    //it is not needed for persisting, but here you can also
    //add user to roles.
    em.persist(users);
    em.persist(r);
    tx.commit();
于 2012-04-22T09:10:04.433 回答