(一)、多对一
示例:一个用户(User
)只能有一个角色(Role
),一个角色(Role
)可以对应多个用户(User
),User 表通过role_id
和 Role 表的id
相关联。
1.映射关系创建
- @ManyToOne:表对应关系;
mapperBy:在关联表中的映射; - @JoinColumn:当前表与其它表关联的
外键
;
name:外键名称。
注:
- 重写
toString
方法不要造成死循环; - 项目配置文件中添加配置,开启懒加载:
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
表 User:
...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
/**
* @ManyToOne:多对一
* @JoinColumn:与其它表关联的外键
*/
@ManyToOne
@JoinColumn(name = "role_id")
private Role role;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", role=" + role.getRole_name() +
'}';
}
...
}
表 Role:
...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
/**
* @OneToMany:一对多
* mapperBy:关联User表外键
*/
@OneToMany(mappedBy = "role")
private Set<User> users = new HashSet<>();
@Override
public String toString() {
return "Role{" +
"id=" + id +
", role_name='" + role_name + '\'' +
'}';
}
...
}
2.测试
...
@Autowired
private UserRepository userRepository;
@Test
void testOneToMany(){
List<Role> roles = new ArrayList<>();
Role role = new Role();
role.setRole_name("管理员");
roles.add(role);
Role role1 = new Role();
role1.setRole_name("VIP会员");
roles.add(role1);
Role role2 = new Role();
role2.setRole_name("会员");
roles.add(role2);
System.out.println("一对多:");
List<User> users = userRepository.findAll();
for (User user : users) {
System.out.println(user.toString());
int i = user.getId() % 2 == 0 ? 1 : (user.getId() % 3 == 0 ? 2 : 0);
user.setRole(roles.get(i));
userRepository.save(user);
}
System.out.println("一对多更新:");
List<User> users2 = userRepository.findAll();
for (User user : users2) {
System.out.println(user);
}
}
...
(二)、多对多
示列:*一个User
对应可能对应多个Menu
,一个Menu
也可能对应多个User
,两个表都通过id
相关联。
1.表关系创建
- @ManyToMany(表间关系)
cascade(级联操作)详情见:资料1,资料2
CascadeType.ALL
:级联所有实体状态转换;
CascadeType.PERSIST
:持久化,级联保存;
CascadeType.MERGE
:级联实体合并操作;
CascadeType.REMOVE
:级联实体删除操作;
CascadeType.REFRESH
:级联实体刷新操作;
CascadeType.DETACH
:级联实体分离操作;
mapperBy:映射字段(关联表字段); - @JoinTable(中间表)
name:中间表名称(名称任意);
joinColumns(当前表与中间表关联字段信息)
name:中间表与当前表关联的字段(任意定义);
referencedColumnName:当前表与中间表关联的字段(当前表中的字段)
inverseJoinColumns:关联表与中间表关联字段信息。
表 Role:
...
@ManyToMany(cascade = CascadeType.ALL)
/**
* @JoinTable:中间表
* name:中间表名称(随便定义)
* joinColumns:当前表中主键所关联的中间表中的外键字段
* name:中间表与当前表关联的字段(任意定义)
* referencedColumnName:当前表与中间表关联的字段(当前表中的字段)
* inverseJoinColumns:关联表与当前表关联的字段(任意定义)
*/
@JoinTable(name = "role_menu",
joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "menu_id", referencedColumnName = "id")})
private Set<Menu> menus = new HashSet<>();
...
表 menu:
...
@ManyToMany(mappedBy = "menus")
private Set<Role> roles = new HashSet<>();
@Override
public String toString() {
return "Menu{" +
"id=" + id +
", Work='" + Work +
'}';
}
...
2.测试
...
@Autowired
private RoleRepository roleRepository;
@Autowired
private MenuRepository menuRepository;
@Test
void testManyToMany() {
Menu menu0 = new Menu();
menu0.setWork("学习" );
Menu menu1 = new Menu();
menu1.setWork("看书");
Menu menu2 = new Menu();
menu2.setWork("打游戏");
System.out.println("多对多查询 Role:");
List<Role> roles = roleRepository.findAll();
for (Role role : roles) {
System.out.println(role.toString());
Set<Menu> menus = new HashSet<Menu>();
menus.add( role.getId() % 2 == 0 ? menu0 : (role.getId() % 3 == 0 ? menu1 : menu2));
role.setMenus(menus);
roleRepository.save(role);
}
System.out.println("多多多查询 Role:");
List<Role> roles = roleRepository.findAll();
for (Role role : roles) {
System.out.println(role);
}
System.out.println("多对多查询 Menu:");
List<Menu> menus = menuRepository.findAll();
for (Menu menu : menus) {
System.out.println(menu);
}
}
...