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

2ul0zpep  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(127)

我与UserRole JPA实体之间存在Many-to-Many关系。当我尝试保存实体时,UserRole实体都将持久化在表中,但连接表不会随记录一起插入。
用户实体

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

角色实体

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

客户类别

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

我哪里做错了?

t40tm48m

t40tm48m1#

您已经Map了一个双向关系,但是只在对象模型中设置了它的一端-错误的一端。如果存在差异,拥有方将控制外键的值,并且由于您将拥有方留空,因此不会设置它们。您负责设置关系的两端,并使它们与数据库中所需的内容保持同步。
由于您没有在关系上设置级联选项,因此您还负责独立于用户持久化角色。

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

另外,您在Lombok的实体中使用Set时使用“@EqualsAndHashCode”生成。不要这样做!
Set使用equals/hashcode逻辑来确定两个对象是否相同,以过滤掉重复的对象,而Lombok生成这些方法来使用可变字段。(即本用例),ID为空,并且在JPA中设置时会发生变化。如果您不知道Java equals/hashcode逻辑对应用程序会有什么影响,那么最好保持这些逻辑。请尝试在模型中使用List和/或不要让Lombok为您生成这些方法。

相关问题