【问题标题】:Hibernate user_roles table will not update when using ManyToOne relationship使用 ManyToOne 关系时,休眠 user_roles 表不会更新
【发布时间】:2018-11-23 03:13:38
【问题描述】:

我有 3 个表,用户、角色和用户角色。用户有一个由“用户”与 CascadeType.Merge 映射的 OneToMany 关系,并且 user_role 与 cascadeTypes.All 有 2 个 ManyToOne 关系,但是 user_table 在运行休眠时从不填充数据。相反,值仅填充在用户和角色表中,而不是 user_role 表中。

用户表定义

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="Id", nullable=false, updatable = false)
private Long id;

private String username;
private String password;
private String firstName;
private String lastName;

private String email;
private String phone;
private boolean enabled = true;

@OneToMany(mappedBy = "user", cascade=CascadeType.MERGE, fetch = 
FetchType.EAGER)
@JsonIgnore
private Set<UserRole> userRoles = new HashSet<>();

用户角色表:

@Entity
@Table(name="user_role")
public class UserRole implements Serializable {
private static final long serialVersionUID = 890345L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long userRoleId;

@ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL, 
optional=false)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL,  
optional=false)
@JoinColumn(name = "role_id")
private Role role;

public UserRole () {}

public UserRole (User user, Role role) {
    this.user = user;
    this.role = role;
}

public long getUserRoleId() {
    return userRoleId;
}

public void setUserRoleId(long userRoleId) {
    this.userRoleId = userRoleId;
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

public Role getRole() {
    return role;
}

public void setRole(Role role) {
    this.role = role;
}

}

调用从 commandLine Runner 调用的 userServiceImpl 中的 userRepository.save()。

@Service

公共类 UserServiceImpl 实现 UserService {

private static final Logger LOG = LoggerFactory.getLogger(UserSecurityService.class);


@Autowired
private UserRepository userRepository;

@Autowired
private RoleRepository roleRepository;


// Indicates a  Database Transaction
@Transactional
public User createUser(User user, Set<UserRole> userRoles) {
    User localUser = userRepository.findByUsername(user.getUsername());

    if(localUser != null) {
        LOG.info("User with username {} already exist. Nothing will be done. ", user.getUsername());
    } else {


        for (UserRole ur : userRoles) {
            roleRepository.save(ur.getRole());
        }

        Set<UserRole> currentRoles =user.getUserRoles();

        currentRoles.addAll(userRoles);
        user.setUserRoles(currentRoles);


        localUser = userRepository.save(user);
    }

    return localUser;    
}

}

主类 Run()

    public void run(String... args) throws Exception {
    User user1 = new User();
    user1.setFirstName("John");
    user1.setLastName("Adams");
    user1.setUsername("j");
    user1.setPassword(SecurityUtility.passwordEncoder().encode("p"));
    user1.setEmail("JAdams@gmail.com");
    Set<UserRole> userRoles = new HashSet<>();
    Role role1 = new Role();
    role1.setRoleId(1);
    role1.setName("ROLE_USER");
    userRoles.add(new UserRole(user1, role1));

    userService.createUser(user1, userRoles);
}

【问题讨论】:

  • 我们真的需要 3 个 user_role 表吗?
  • 是的,user_role 表是一个关联表,用于解决用户和角色共享的多对多关系。

标签: java spring hibernate jpa orm


【解决方案1】:

CascadeType.MERGE 只会级联合并事件。持久事件不会级联,因此如果您尝试保存新用户,持久事件将不会级联到 User_role,并且不会将任何条目插入 user_role 表。

尝试添加 CascadeType.PERSIST 或更改为 CascadeType.ALL 以便将记录级联保存在数据库中。

@OneToMany(mappedBy = "user", cascade={CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.EAGER)

您可以在此答案中找到有关 Cascade 事件的更多信息:What do REFRESH and MERGE mean in terms of databases?

【讨论】:

  • 添加此级联类型时,休眠现在失败并出现错误:javax.persistence.EntityExistsException:具有相同标识符值的不同对象已与会话相关联此失败在调用 save() 后立即发生在 UserServiceImpl 类中:localUser = userRepository.save(user);
【解决方案2】:

通过实现 JPA 实体管理器,我能够将数据持久保存到 user_role 关联表。实例化了一个新的 EntityManager 类,并通过 javax.persistence .merge() 方法对数据进行了持久化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2012-04-08
    • 2014-07-02
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多