提问者:小点点

更新一对多实体将父级设置为 null


我在@OneToMany关系链接的用户实体上有一个角色实体列表。当我更改用户实体上的列表时,即更改角色,Hibernate会删除旧角色并根据需要添加新角色。但是,外键字段在角色实体上设置为 null。

您能否解释为什么 foregign 键字段为空,以及我将如何更改它以便在更新时被拾取?

用户.java

@SerializedName("userrole")
@Expose
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Role>   userRoles = new ArrayList<Role>();

角色.java

@ManyToOne
@JoinColumn(name = "user")
private User user;

表前

+----+------+------------------------+
| id | role | user                   |
+----+------+------------------------+
|  1 |    0 | digby.tyson@gmail.com  |
|  2 |    1 | digby.tyson@gmail.com  |
|  3 |    2 | digby.tyson@gmail.com  |
|  4 |    3 | digby.tyson@gmail.com  |
|  5 |    4 | digby.tyson@gmail.com  |
|  6 |    5 | digby.tyson@gmail.com  |
|  7 |    6 | digby.tyson@gmail.com  |
|  8 |    7 | digby.tyson@gmail.com  |
|  9 |    5 | ronny.polley@gmail.com |
| 10 |    6 | ronny.polley@gmail.com |
| 11 |    7 | reed.robert@gmail.com  |
+----+------+------------------------+

表后

+----+------+------------------------+
| id | role | user                   |
+----+------+------------------------+
|  9 |    5 | ronny.polley@gmail.com |
| 10 |    6 | ronny.polley@gmail.com |
| 11 |    7 | reed.robert@gmail.com  |
| 12 |    0 | NULL                   |
| 13 |    1 | NULL                   |
| 14 |    2 | NULL                   |
| 15 |    5 | NULL                   |
| 16 |    6 | NULL                   |
| 17 |    7 | NULL                   |
+----+------+------------------------+

Hibernate操作

Hibernate: select userroles0_.user as user3_2_0_, userroles0_.id as id1_1_0_, userroles0_.id as id1_1_1_, userroles0_.role as role2_1_1_, userroles0_.user as user3_1_1_ from role userroles0_ where userroles0_.user=?
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: insert into role (role, user) values (?, ?)
Hibernate: update user set first_name=?, last_name=?, middle_name=?, organisation_id=? where email=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?
Hibernate: delete from role where id=?

更新

根据注释中的请求调用数据库的方法

@Override
@Transactional
public User update(User user) throws UserNotFoundException {
    String updatedUserEmail = user.getEmail();

    if (userRepository.findByEmail(updatedUserEmail) == null)
        throw new UserNotFoundException();

    return userRepository.save(user);

}

@Transactional
public interface UserRepository extends CrudRepository<User, Long> {

提前感谢您的任何帮助。


共2个答案

匿名用户

映射是正确的,现在您要实现的是,当从用户中删除角色时,您希望删除该角色(orphanRemoval = true)。

这是一个双向关联,因此您需要做的是在两端进行更改以保持对象模型的一致性:

// remove role from user one-to-many
user.getUserRoles().remove(roleToBeDeleted);
// remove the many-to-one association
roleToBeDeleted.setUser(null);

匿名用户

我用EntityManager并使用Hibernate做了这个,它似乎工作正常。您是否将旧角色从列表中删除

用户:

@Entity
public class User {
    @Id private String email;

    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Role> userRoles = new ArrayList<Role>();

角色:

@Entity
public class Role {
    @Id @GeneratedValue private Long id;

    @ManyToOne
    private User user;

运行方式为:

User u = em.find(User.class, "test@test.com");
Role e = new Role();
e.setUser(u);
u.getUserRoles().remove(0);
u.getUserRoles().add(e);
em.merge(u);

给我:

Hibernate: insert into Role (user_email, id) values (?, ?)
Hibernate: delete from Role where id=?
Hibernate: select * from role

在角色表中只有一行:

[2, test@test.com]