Каков наиболее эффективный способ сопоставить отношения @ManyToMany с JPA и Hibernate? - PullRequest
1 голос
/ 04 августа 2020

Я знаю только основы DB и JPA / Hibernate. Мне нужно управлять таблицей пользователей, в которой у пользователя может быть много ролей. Роли содержатся в таблице каталога, которую в моем формуляре пользователя я не претендую на управление / изменение, мне просто нужны значения каталога в качестве ссылки для добавления или удаления моего пользователя. Я думаю, что лучшим подходом было бы создать таблицу отношений между пользователем и ролью, чтобы удерживать пользователей и их роли «User_Roles» (если нет более эффективного подхода).

Мне не разрешено изменять роль entity, поскольку он используется для разных целей во многих других областях моего приложения, которые не зависят от таблицы User.

Я видел много примеров, но до сих пор не знаю, какой именно из них соответствует мои конкретные c потребности. Как я могу сопоставить моего пользователя и его роли в одной сущности с JPA и Hibernate?

Может быть, следующее изображение лучше описывает то, что я хочу: введите описание изображения здесь

Заранее большое спасибо за ваши ответы.

Ответы [ 3 ]

3 голосов
/ 04 августа 2020

В вашем случае вы должны использовать @ManyToMany для связывания обеих таблиц.

Это должно выглядеть следующим образом:

@Entity
@Table(name = "User")
public class User { 
   ...
   @ManyToMany
   @JoinTable(name = "User_Roles", joinColumn = "id_person")
   private Set<Role> roles = new HashSet<>;
}

@Entity
@Table(name = "Role")
public class Role { 
   ...
   @ManyToMany(mappedBy = "roles")
   private Set<User> users = new HashSet<>;
}
1 голос
/ 04 августа 2020

То, что вы описываете, является отношением «один ко многим», но оно находится между User и таблицей соединения - User_Roles. Поскольку мало что можно сделать, чтобы избежать таблицы соединения, лучше всего было бы использовать @ManyToMany с аннотациями @JoinTable для отображения взаимосвязи. Не забудьте использовать Set вместо List. Тогда вам не нужна сущность для таблицы joinint.

Вы можете найти обсуждение этого topi c в этом сообщении в блоге .

0 голосов
/ 04 августа 2020

Как видно из приведенного выше экрана, пользователю может быть назначено более одной роли. т.е. 1 пользователь может быть сопоставлен с несколькими ролями, а 1 роль может быть сопоставлена ​​с несколькими пользователями.

Следовательно, отношения между пользователем и ролью - многие ко многим. третья таблица, которая называется таблицей сопоставления.

Итак, в вашем примере у нас есть следующие таблицы: -

  • user

  • user_roles

  • role

      @Entity
     @Table(name = "user")
     @JsonInclude(JsonInclude.Include.NON_NULL)
     public class User {
         @Id
         @SequenceGenerator(name = "USER_ID_GENERATOR", sequenceName = "USER_SEQ",
                 allocationSize = 1)
         @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_ID_GENERATOR")
         @Column(name = "user_id")
         private Long userId;
    
         @OneToOne
         @JoinColumn(name = "persion_id")
         private person person;`
         enter code
         here`
    
         @Basic
         @Column(name = "date")
         private Date date;
    
         @Basic
         @Column(name = "observations")
         private String observations;
    
         @Basic
         @Column(name = "text")
         private String text;
    
         @JsonIgnore
         @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
         private List<UserRoles> users = new ArrayList<>();
    
     }
    

    @ Entity @Table (name = "role") @JsonInclude (JsonInclude.Include.NON_NULL) publi c class Role {

     @Id
     @SequenceGenerator(name = "ROLE_ID_GENERATOR", sequenceName = "ROLE_SEQ",
             allocationSize = 1)
     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ROLE_ID_GENERATOR")
     @Column(name = "role_id")
     private Long roleId;
    
     @Basic
     @Column(name = "id1")
     private Long idOne;
    
     @Basic
     @Column(name = "id1")
     private Long idTwo;
    
     @Basic
     @Column(name = "id1")
     private Long idThree;
    
     @Basic
     @Column(name = "text")
     private String text;
    
     @JsonIgnore
     @OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
     private List<UserRoles> users = new ArrayList<>();
    

    }

    @ Entity @Getter @Setter @Table (name = "user_roles") @JsonInclude (JsonInclude.Include.NON_NULL) @Audited publi c класс UserRoles {

     private static final long serialVersionUID = 1L;
    
     @EmbeddedId
     UserRolesKey userRoleId;
    
     @JsonIgnore
     @ManyToOne(fetch = FetchType.LAZY)
     @MapsId("role_id")
     @JoinColumn(name = "role_id")
     Roles role;
    
     @JsonIgnore
     @ManyToOne(fetch = FetchType.LAZY)
     @MapsId("user_id")
     @JoinColumn(user_id)
     User user;
    
     @PrePersist
     private void prePersist() {
         super.onPrePersist();
         if (this.getId() == null) {
             UserRolesKey mapKey = new UserRolesKey();
             mapKey.setRoleId(this.getRole().getRoleId());
             mapKey.setUserRoleId(this.getUser().getUserId());
             this.setId(mapKey);
         }
     }
    

    }

При сохранении вам просто нужно заполнить объект пользователя всеми объектами сопоставления uaerRoles и сохранить его. jpa сохранит все детали.

при обновлении роли, назначенной пользователю, вам необходимо получить сущность пользователя и обновить сопоставление, добавив новую сущность userRoles и аннулировав время, которое будет удалено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...