我与User
和Role
JPA实体之间存在Many-to-Many
关系。当我尝试保存实体时,User
和Role
实体都将持久化在表中,但连接表不会随记录一起插入。
用户实体
@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);
}
我哪里做错了?
1条答案
按热度按时间t40tm48m1#
您已经Map了一个双向关系,但是只在对象模型中设置了它的一端-错误的一端。如果存在差异,拥有方将控制外键的值,并且由于您将拥有方留空,因此不会设置它们。您负责设置关系的两端,并使它们与数据库中所需的内容保持同步。
由于您没有在关系上设置级联选项,因此您还负责独立于用户持久化角色。
另外,您在Lombok的实体中使用Set时使用“@EqualsAndHashCode”生成。不要这样做!
Set使用equals/hashcode逻辑来确定两个对象是否相同,以过滤掉重复的对象,而Lombok生成这些方法来使用可变字段。(即本用例),ID为空,并且在JPA中设置时会发生变化。如果您不知道Java equals/hashcode逻辑对应用程序会有什么影响,那么最好保持这些逻辑。请尝试在模型中使用List和/或不要让Lombok为您生成这些方法。