JPA坚持不懈

时间:2012-04-22 08:27:04

标签: java mysql jpa

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

我已经生成了实体类(见下文),我将数据持久保存到用户和角色表没有问题,但是我很难将任何内容遗留给users_has_roles加入表,因此目前我的所有用户都没有被分配角色。在我发疯之前,有人可以让我摆脱痛苦,并告诉我应该如何将users_user_id和相应的roles_role_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);

2 个答案:

答案 0 :(得分: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,但您也可以使用任何其他符合您需求的类型。)

答案 1 :(得分:6)

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

为了保持它你必须关心拥有方的关系(没有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();