Spring + JPA / Hibernate不保存多对多映射

时间:2017-12-20 10:28:55

标签: java spring hibernate jpa

场合

我有RoleEntityUserEntityRoleEntity包含UserEntity列表,反之亦然,从而产生Many-To-Many关系。

我的UserEntity

public class UserEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String username;
    @Column(name = "first_name", nullable = false)
    private String firstName;
    @Column(name = "last_name", nullable = false)
    private String lastName;
    @Column(nullable = false)
    private String email;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
    @JoinTable(name = "uas_user_role",
        joinColumns = @JoinColumn(name = "uas_user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "uas_role_id", referencedColumnName = "id"),
        uniqueConstraints = {
        @UniqueConstraint(columnNames = {"uas_user_id", "uas_role_id"})}
    )
    private Set<RoleEntity> roles = new HashSet<>();
...
}

我的RoleEntity

public class RoleEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(unique = true, nullable = false)
    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<UserEntity> users;

    @ManyToMany
    @JoinTable(
        name = "uas_role_permission",
        joinColumns
        = @JoinColumn(name = "uas_role_id", referencedColumnName = "id"),
        inverseJoinColumns
        = @JoinColumn(name = "uas_permission_id", referencedColumnName = "id"),
        uniqueConstraints = {
        @UniqueConstraint(columnNames = {"uas_role_id", "uas_permission_id"})}
    )
    private Set<PermissionEntity> permissions;
...
} 

目标

现在我想通过更新单个实体来更改映射。例如,我想将UserEntity添加到ID为1的RoleEntity

{
    "id": 1,
    "name": "Admin_Role",
    "users": [{"id": 1}
    ]
}

将此RoleEntity保存到其角色存储库(JPARepository.saveAndFlush(Serializable)),成功解析隐含的UserEntity并返回更新后的RoleEntity

 {
    "id": 1,
    "name": "Admin_Role",
    "users": [{
            "id": 1,
            "username": "admin",
            "firstName": "Administrator",
            "lastName": "Administrator",
            "email": "info@example.com",
        }
    ]
}

问题

我的测试全部通过,因为我只检查了save命令的返回值。 现在我发现在坚持后roleRepository.findOne(1)进行RoleEntity时,我会收到以下{ "id": 1, "name": "Admin_Role", "users": [] }

UserEntity

spring.jpa.show-sql=true映射未持久化。 同样在设置SELECT时,我发现在saveAndFlush命令期间只执行@Transactional public RoleDto updateRole(RoleDto role) { RoleEntity roleEntity = roleRepository.findOne(role.getId()); if (roleEntity==null){ throw new ResourceNotFoundException(); } final RoleEntity savedRoleEntity = roleRepository.saveAndFlush(roleEntity); savedRoleEntity.getUsers().forEach(user -> user.getRoles().add(savedRoleEntity)); return savedRoleEntity; } 次操作。 我只想创建映射,并且不想允许编辑映射实体,这就是我禁用任何级联的原因。

我预计通过这种方法可以创建映射。我究竟做错了什么?

解决方案

正如 Amer Qarabsa 所述: 要创建双向映射,需要在两端进行设置。保存实体后添加一行已经成功了:

.saveAndFlush(roleEntity)

使用RoleEntity我首先更新UserEntity并让JPA解析RoleEntity。在此之后,我只需将UserEntity设置为角色的每个CREATE TABLE books(price DECIMAL(20,6)) #ENGINE=MyISAM; INSERT INTO `books`(`price`) VALUES (176.00), (337.00), (234.00), (180.00), (135.00), (72.00), (72.00), (81.00), (135.00), (113.00), (162.00); SELECT * FROM books; 。在我的情况下,我不需要手动保留,因为事务将负责持久保存任何未保存的更改。

1 个答案:

答案 0 :(得分:2)

在双向关系中它做起来并不简单,你不能把json和它映射到实体这么简单,关系的每一面都应该引用另一面,所以在你的情况下你需要采取角色实体内的每个使用者并设置它的角色实体然后保存。