spring-data-jpa 1对多 多对多

1.1对1

Worker对应department

一个员工对应一个部门

表结构

worker

spring-data-jpa 1对多 多对多

department

spring-data-jpa 1对多 多对多

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.先添加部门再添加工人

结果: 成功

spring-data-jpa 1对多 多对多

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

顺带部门信息一起查询出来

spring-data-jpa 1对多 多对多

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

spring-data-jpa 1对多 多对多

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 + "]";
	}
}

spring-data-jpa 1对多 多对多

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

spring-data-jpa 1对多 多对多

中间表

spring-data-jpa 1对多 多对多

测试

(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,

spring-data-jpa 1对多 多对多

中间表也关联上了数据, 这与上面user的添加结果不同. 

spring-data-jpa 1对多 多对多

由此可以得出, 是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集合解决重复性问题.