简体   繁体   English

Jpa 不在多对多关系的连接表中插入记录

[英]Jpa not inserting the record in the join table for many to many relatioship

I have a Many-to-Many relationship with User and Role JPA entities.我与UserRole JPA 实体存在Many-to-Many关系。 When I try to save the entities, both User and Role entities gets persisted in the table, but the junction table is not getting inserted with the records, Where am I going wrong当我尝试保存实体时, UserRole实体都保留在表中,但联结表没有插入记录,我哪里出错了

User Entity用户实体

@Entity
@Table(name="users")
@Data
@NoArgsConstructor
@EqualsAndHashCode(exclude = "roles")
@ToString(exclude = "roles")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    private String name;
    private String password;
    private double salary;
    
    public User(String name, String password, double salary) {
        super();
        this.name = name;
        this.password = password;
        this.salary = salary;
    }
    
    
    @ManyToMany(
            mappedBy = "users")
    private Set<Role> roles = new HashSet<>();
    
    
    public void addRole(Role role) {
        this.roles.add(role);
        role.getUsers().add(this);
    }
}

Role Entity角色实体

@Entity
@Table(name = "roles")
@Data
@NoArgsConstructor
@EqualsAndHashCode(exclude = "users")
@ToString(exclude = "users")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String roleName;

    public Role(String roleName) {
        super();
        this.roleName = roleName;
    }
    
    @ManyToMany
    @JoinTable(
            name="user_roles",
            joinColumns = @JoinColumn(name="role_id", nullable = false),
            inverseJoinColumns = @JoinColumn(name="user_id", nullable = false)
            )
    private Set<User> users = new HashSet<>();
}

Client class客户 class

@EventListener(ApplicationReadyEvent.class)
    public void onApplicationStartup(ApplicationReadyEvent event) {
        
        User kiran = new User("kiran", this.passwordEncoder.encode("welcome"), 4500000);
        
        User vinay = new User("vinay", this.passwordEncoder.encode("welcome"), 4500000);        
        
        Role userRole = new Role("ROLE_USER");
        
        Role adminRole = new Role("ROLE_ADMIN");
        
        
        kiran.addRole(userRole);
        
        vinay.addRole(userRole);
        vinay.addRole(adminRole);
        
        this.userRepository.save(kiran);
        this.userRepository.save(vinay);
        
    }

Where am I going wrong?我哪里错了?

You've mapped a bidirectional relationship, but are only setting one side of it in your object model - the wrong side.您已经映射了双向关系,但仅在 object model 中设置了它的一侧 - 错误的一侧。 Should there ever be a discrepancy, the owning side controls the values of foreign keys, and since you have left the owning side empty, they aren't being set.如果存在差异,拥有方控制外键的值,并且由于您将拥有方留空,因此不会设置它们。 You are responsible to set both sides of relationships and keeping them in synch with what you want in the database.您有责任设置关系的双方,并使它们与您在数据库中想要的内容保持同步。

Since you don't have cascade options set on the relationships, you are also responsible for persisting the roles independently from the Users.由于您没有在关系上设置级联选项,因此您还负责独立于用户保留角色。 Something more like:更像是:

public void onApplicationStartup(ApplicationReadyEvent event) {
  // you might want to check to see if these roles already exists and use those instead of creating new ones
  Role userRole = roleRepository.save(new Role("ROLE_USER"));
  Role adminRole = roleRepository.save(new Role("ROLE_ADMIN"));

  User kiran = new User("kiran", this.passwordEncoder.encode("welcome"), 4500000);
  kiran.addRole(userRole);//assumes this adds the user to the role.users as well.
  this.userRepository.save(kiran);

  User vinay = new User("vinay", this.passwordEncoder.encode("welcome"), 4500000);  
  vinay.addRole(userRole);
  vinay.addRole(adminRole);
  this.userRepository.save(vinay);
}

Also, you are using Set in your entities with Lombok using "@EqualsAndHashCode" generation.此外,您正在使用“@EqualsAndHashCode”生成在 Lombok 的实体中使用 Set。 Don't do that!不要那样做!

Set uses the equals/hashcode logic to determine if two objects are the same to filter out duplicates, while Lombok generates those methods to use what are mutable fields. Set 使用 equals/hashcode 逻辑来确定两个对象是否相同以过滤掉重复项,而 Lombok 生成这些方法以使用可变字段。 In the case you have new entities in those sets (ie this usecase), the IDs are null and will change when set from JPA. You are better off keeping Java equals/hashcode logic if you don't know what effects those will have on your application.如果你在这些集合中有新实体(即这个用例),ID 是 null 并且当从 JPA 开始设置时会改变。如果你不知道这些会产生什么影响,你最好保留 Java 等于/哈希码逻辑你的申请。 try using either List in your model and/or not having Lombok generate those method for you.尝试在您的 model 中使用任一 List 和/或不让 Lombok 为您生成这些方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM