spring-data-jpa 1对多 多对多
1.1对1
Worker对应department
一个员工对应一个部门
表结构
worker
department
model
Worker.java
@Entity
@Getter
@Setter
public class Worker {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 工号
@Column(name = "worker_id", unique = true)
private String workerId;
// 姓名
private String name;
//多个工人---1个部门
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "department_id")
private Department department;
}
Department.java
@Entity
@Getter
@Setter
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
/* a) 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
b) mappedBy标签一定是定义在the owned side(被拥有方的),他指向theowning side(拥有方);
c) 关系的拥有方负责关系的维护,在拥有方建立外键。所以用到@JoinColumn
d)mappedBy跟JoinColumn/JoinTable总是处于互斥的一方*/
//1个部门有多个workers, one to many
@OneToMany(mappedBy="department",fetch = FetchType.EAGER)
private Set<Worker> workers;
//1个部门对应多个users one to many
@OneToMany(mappedBy="department",fetch = FetchType.EAGER)
private Set<User> users;
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
//FetchType.EAGER意思是不用懒加载. 直接加载关联信息
}
WorkerRepository.java
public interface WorkerRepository extends JpaRepository<Worker, Long> {
public Worker findById(Long id);
public Worker findByWorkerId(String workerId);
public Page<Worker> findAll(Specification<Worker> specification, Pageable pageable);
public List<Worker> findAll(Specification<Worker> specification);
//public List<Worker> findByWorkerStatusAndClassesTeamId(Byte status, Integer teamId);
}
测试
1. 在不存在部门的情况下添加工人
结果:失败
这里不会为不存在的部门进行关联保存
//测试会不会自动生成department
//不行, 看来必须先存上department, 再来维护关系
@Test
public void addWorker(){
Worker w = new Worker();
Department d = new Department();
d.setId(5);
d.setName("生产部");
//Department d = departmentRepository.findOne(1);
w.setDepartment(d);
w.setName("小好");
w.setWorkerId("003");
workerRepository.save(w);
}
2.先添加部门再添加工人
结果: 成功
@Test
public void addWorker(){
Worker w = new Worker();
/* Department d = new Department();
d.setId(5);
d.setName("生产部");*/
Department d = departmentRepository.findOne(1);
w.setDepartment(d);
w.setName("小好");
w.setWorkerId("003");
workerRepository.save(w);
}
3.查询工人
@Test
public void getWorker(){
List<Worker> workers = workerRepository.findAll();
System.out.println(workers);
}
顺带部门信息一起查询出来
2. 1对多
model
还是上面的那样, 1个department对应多个worker, model如上面的.
测试
@Test
public void getDepartmentList(){
//只能查到部门的基本信息, list中的信息查询不到.
List<Department> departments = departmentRepository.findAll();
if (departments.size()>0) {
//Set<Worker> workers = departments.get(0).getWorkers();
Set<Worker> workers = departments.get(0).getWorkers();
System.out.println(workers);
}
System.out.println(departments);
}
3.多对多
User.java
@Entity(name = "Account")
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// 登录用户名
@Column(name = "login_name", unique = true)
private String loginName;
//多个用户对应同一个角色, 一个角色对应多个用户
@ManyToOne
@JoinColumn(name = "role_id")
private Role role;
//一个用户对应一个工人
@OneToOne
@JoinColumn(name = "worker_id")
private Worker worker;
//多个用户, 对应一个部门
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
//多个用户对应多个NotifyConfig
@ManyToMany(mappedBy = "users",fetch = FetchType.EAGER)
private List<WarningNotifyConfig> warningNotifyConfig;
@Override
public String toString() {
return "User [id=" + id + ", loginName=" + loginName + "]";
}
}
WarningNotifyConfig.java
@Getter
@Setter
@Entity
public class WarningNotifyConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Boolean enableEmail;
@ManyToMany
@JoinTable(name = "notify_user", joinColumns = @JoinColumn(name = "config_id"), inverseJoinColumns = @JoinColumn(name = "user_id"))
private List<User> users;
}
中间表
测试
(1)当notify存在的时候, 添加user
@Test
public void addUser(){
User u = new User();
u.setDepartment(departmentRepository.findOne(1));
u.setLoginName("33789");
u.setRole(roleRepository.findOne(2));
Worker w1 = new Worker();
w1.setId(2L);//这个必须有
w1.setName("王永强无部门");
w1.setWorkerId("002");
u.setWorker(w1);
List<WarningNotifyConfig> warningNotifyConfigs = new ArrayList<WarningNotifyConfig>();
WarningNotifyConfig warningNotifyConfig = warningNotifyConfigRepository.findOne(5);
warningNotifyConfigs.add(warningNotifyConfigRepository.findOne(5));
u.setWarningNotifyConfig(warningNotifyConfigs);
//维护关系放在warnNotifyConfig那里了, 保存user不会修改中间表
userRepository.save(u);
}
以上: user添加成功, 但是 中间表没有维护. 我推测是因为维护关系的任务是落在了WarningNotifyConfig那里.
(2)在存在user的情况下, 添加WarningNotifyConfig
//在先有user的情况下, 可以这样添加notify
@Test
public void setUserAndSave(){
//WarningNotifyConfig w = warningNotifyConfigRepository.getOne(1);//这句报no Session的错
WarningNotifyConfig w = new WarningNotifyConfig();//这句正常添加
w.setEnableEmail(false);
List<User> list = new ArrayList<User>();
User user = new User();
user.setId(22);
list.add(user);
w.setUsers(list);
warningNotifyConfigRepository.save(w);
}
测试结果:
添加了WarningNotifyConfig,
中间表也关联上了数据, 这与上面user的添加结果不同.
由此可以得出, 是WarningNotifyConfig维护了中间表.
这跟User的这个代码有关么?
//多个用户对应多个NotifyConfig
@ManyToMany(mappedBy = "users",fetch = FetchType.EAGER)
private List<WarningNotifyConfig> warningNotifyConfig;
(3)获取user
@Test
public void getUserWhenZhongjianbiaoHasConfig(){
User user = userRepository.findOne(22);
List<WarningNotifyConfig> warningNotifyConfigs = user.getWarningNotifyConfig();
int size = warningNotifyConfigs.size();
if(warningNotifyConfigs.size() > 0){
WarningNotifyConfig wc = warningNotifyConfigs.get(0);
int id=wc.getId();
System.out.println(id);
}
//userRepository.save(user);
}
获取成功, 但是会有两条一样的warningNotifyConfig. 怀疑是department那里影响了, depart的代码修改之后就可以了
@OneToMany(mappedBy="department")
private Set<Worker> workers;
//1个部门对应多个users one to many
@OneToMany(mappedBy="department")
private List<User> users;
但是department就用不了. 所以只能在manytomany的时候也用Set集合解决重复性问题.