一对多
- 一方
@Entity
@Table(name="test_user")
public class User {
private String id;
private List<LoginHistory> loginHistories;
@Id
@GeneratedValue(generator = "uuid-gen")
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
@Column(name ="id",length=32)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
public List<LoginHistory> getLoginHistories() {
return loginHistories;
}
public void setLoginHistories(List<LoginHistory> loginHistories) {
this.loginHistories = loginHistories;
}
}
以上是一方的配置,mappedBy=”被维护端外键属性”,mappedBy指明两个关联的实体Bean中,被维护方的外键属性。只能配置在一方,即关系维护方。
多方
@Entity
@Table(name="test_login_history")
public class LoginHistory {
private String id;
@Id
@GeneratedValue(generator = "uuid-gen")
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
@Column(name ="id",length=32)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.MERGE,}, optional = true)
@JoinColumn(name = "user_id",nullable=true)
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
一对多操作实例
@RequestMapping("login")
public String login(User user,ModelMap map){
LoginHistory loginHistory=new LoginHistory();
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datestr=sdf.format(d);
//NO.1 为多方设置外键属性(即一方的实体)
loginHistory.setUser(user);
loginHistory.setLoginDate(datestr);
loginHistory.setLoginIP("127.0.0.1");
List<LoginHistory> lhlist=new ArrayList<LoginHistory>();
lhlist.add(loginHistory);
//NO.2 将多方的实体,赋值给一方
user.setLoginHistories(lhlist);
//NO.3 只保存一方对象,即可级联保存。
userService.addUser(user);
map.put("status", "success");
return "welcome";
}
许多新手配置时,只有关键的NO.2,NO.3 没有设置NO.1 ,这导致数据库,只保存了一方的实体,而没有级联保存多方的实体。
多对多
下面以User和Role为例子,介绍下多对多。直接上代码了,请自行阅读。
@Entity
@Table(name="test_user")
public class User {
private String id;
@Id
@GeneratedValue(generator = "uuid-gen")
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
@Column(name ="id",length=32)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
private List<Role> roles;
/*
joinColumns写的是本表在中间表的外键名称,
inverseJoinColumns写的是另一个表在中间表的外键名称。
*/
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "fc_role_user", joinColumns = @JoinColumn(name = "fk_user_id"), inverseJoinColumns = @JoinColumn(name = "fk_role_id"))
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
@Entity
@Table(name="test_role")
public class Role {
private String id;//角色id
private String rolename;//角色名称
private List<User> users;
@Id
@GeneratedValue(generator = "uuid-gen")
@GenericGenerator(name = "uuid-gen", strategy = "uuid")
@Column(name ="id",length=32)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name="role_name",length=50)
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
@ManyToMany(fetch = FetchType.LAZY,cascade={CascadeType.PERSIST,CascadeType.MERGE},mappedBy = "roles")
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
// 多对多保存实例【controller】
@RequestMapping("login")
public String login(User user,ModelMap map){
Role role=null;
role=roleService.getRoleByName("admin2");
if(role==null){
role=new Role();
role.setRolename("admin2");
roleService.addRole(role);
}
List<Role> rolelist=new ArrayList<Role>();
rolelist.add(role);
user.setRoles(rolelist);
userService.saveUser(user);
return "welcome";
}
关于多对多的维护端和被维护端,如何确定,我要啰嗦几句。之前因为搞不明白,没少让坑。网上关于维护端和被维护的介绍,大都一笔带过,而且概念模糊,对本人开发,造成了很大的误导。我经过实践,总结如下:
所谓的维护端,就是级联关系的主导方,一般对应多对多关系中“少数”一方,何为“少数”,就拿上边的例子解释,一个系统可以有几万个用户,但角色肯定不会也是几万个,最多也就是十几个,那么角色就是“少数”方,也就是维护方。你的级联属性,要在“少数”方配置,级联保存的时候,你可以直接将少数方,作为一个常用属性,赋值给多的一方,直接保存多的一方,你们之间的关系,也就被保存了。