2017-12-20 10 views
1

상황봄 + JPA/최대 절전 모드하지 대다 매핑

가 나는 RoleEntityUserEntity을 절약. RoleEntity에는 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; 
... 
} 

목표

지금은 하나의 개체를 업데이트 간단하여 맵핑을 변경하고 싶습니다. 예를 들어 내가 가진 RoleEntityUserEntity을 추가 할 ID = 1 :

{ 
    "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": "[email protected]", 
     } 
    ] 
} 
을 반환

문제

내 테스트는 모두 통과했기 때문에 테스트가 모두 통과했습니다. save 명령의 turn 값. 계속 발생 후 roleRepository.findOne(1)을 할 때 지금 내가 발견, 나는 RoleEntity 다음을받을 것이다 :

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

UserEntity 매핑은 지속되지 않았다. 또한 spring.jpa.show-sql=true을 설정할 때 saveAndFlush 명령 중에 SELECT 작업 만 실행됩니다. 매핑 엔티티의 편집을 허용하지 않으려는 경우에만 매핑을 만들려고합니다. 그 이유는 계단식을 비활성화했기 때문입니다.

이 방법을 사용하면 매핑이 생성 될 것으로 예상됩니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

언급 메르 Qarabsa 으로 해결 방법 : 는 양방향 매핑을 만들려면, 그것은 양쪽에 설정해야합니다. .saveAndFlush(roleEntity)

@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; 
} 

내가 먼저 RoleEntity를 업데이트하고 JPA는 UserEntity를 해결 드리겠습니다 : 이미 엔티티를 저장 한 후 한 줄을 추가하면 트릭을 수행합니다. 그 후에 역할의 각 UserEntityRoleEntity을 설정하기 만하면됩니다. 내 경우에는 수동으로 저장하지 않아도됩니다. 트랜잭션이 저장되지 않은 변경 사항을 유지 관리하기 때문입니다.

답변

1

양방향 관계에서이 작업을 수행하는 것이 간단하지 않은 경우 json을 가져 와서 엔티티에 매핑 할 수 없으므로 릴레이션의 각면에 다른면에 대한 참조가 있어야합니다. 따라서 필요한 경우 역할 엔티티 내부의 각 userentity와 역할 엔티티를 설정 한 다음 저장하십시오.

+0

모든 필요한 정보를 얻을 수 있기 때문에 Jpa/Hibernate가 이에 관심을 기울일 것으로 기대했을 것입니다. 그렇다면이 경우가 아닙니까? –

+0

@HerrDerb 아니요, jpa에서 처리 할 수 ​​없습니다. 특히 nullable 시나리오에 대해 생각하는 경우 –

+0

아, 알겠습니다. 사실 아주 간단하게 해결할 수 있습니다. 내 질문에 구체적인 해결책을 추가하겠습니다. 감사. –