8、Spring Data JPA 之 表与表关系建立(一对多)

一对多

Employee 和 Department 两个实体类,部门与员工存在一对多的关系

部门表

@Entity
@Table(name = "t_department")
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "department_id")
    private Integer departmentId;
    @Column(name = "address")
    private String address;
    @Column(name = "phone_number")
    private String phoneNumber;

    /**
     * 使用注解的形式配置多表之间的关系(一对多关系)
     *      1声明关系
     *          @OneToMany
     *              targetEntity = Employee.class 对方对象的字节码对象
     *              mappedBy: 对方配置关系的属性名称
     *              cascade: 配置级联
     *      2配置外键
     *          @JoinColumn
     *              name  外键字段名称
     *              referencedColumnName 参照的主表的主键字段名称
     *       在一的一方添加了外键配置,对于一的一方也具备了维护外键的作用
     */
//    @OneToMany(targetEntity = Employee.class)
//    @JoinColumn(name = "fk_department_employee", referencedColumnName = "department_id")
    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
    private Set<Employee> employees = new HashSet<>();

    public Set<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Set<Employee> employees) {
        this.employees = employees;
    }

    public Integer getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentId(Integer departmentId) {
        this.departmentId = departmentId;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    @Override
    public String toString() {
        return "Department{" +
                "departmentId=" + departmentId +
                ", address='" + address + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                '}';
    }
}

员工表

/**
 * 1.实体类和表的映射关系
 *      @Entity
 *      @Table
 * 2.类中属性和表中字段的映射关系
 *      @Id
 *      @GeneratedValue
 *      @Column
 */
@Entity
@Table(name = "t_employee")
public class Employee{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "emp_id")
    private Integer empId;
    @Column(name = "user_name")
    private String userName;
    @Column(name = "gender")
    private String gender;

    /**
     * 配置多对一的关系
     *      配置表关系
     *      配置外键(中间表)
     */
    @ManyToOne(targetEntity = Department.class)
    @JoinColumn(name = "fk_department_employee", referencedColumnName = "department_id")
    private Department department;

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "empId=" + empId +
                ", userName='" + userName + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}

接口

import java.util.List;

/**
 * 符合Spring Data Jpa 的 dao层接口规范
 *      JpaRepository<操作的实体类类型,实体类中主键属性的类型>
 *          #封装了基本CRUD操作
 *      JpaSpecificationExecutor <操作的实体类类型>
 *          #封装了复杂查询(分页)
 */
public interface DepartmentDao extends JpaRepository<Department, Integer>,JpaSpecificationExecutor<Department>{

}
/**
 * 符合Spring Data Jpa 的 dao层接口规范
 *      JpaRepository<操作的实体类类型,实体类中主键属性的类型>
 *          #封装了基本CRUD操作
 *      JpaSpecificationExecutor <操作的实体类类型>
 *          #封装了复杂查询(分页)
 */
public interface EmployeeDao extends JpaRepository<Employee, Integer>,JpaSpecificationExecutor<Employee>{

}

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
public class OneToManyTest {
    @Autowired
    private DepartmentDao departmentDao;

    @Autowired
    private EmployeeDao employeeDao;

    /**
     * 保存员工与部门
     */
    @Test
    @Transactional
    @Rollback(false)
    public void testAdd(){
        Department department = new Department();
        department.setAddress("南海省");
        department.setPhoneNumber("8888-8888");

        Employee employee = new Employee();
        employee.setGender("男");
        employee.setUserName("小黑");

        /**
         * 配置了部门 → 员工 的关系(一对多的关系)
         *      从员工的角度上,发送两条insert语句,发送一条更新语句更新数据库(更新外键)
         * 由于我们配置了员工 → 部门 的关系,员工可以对外键进行维护
         */
        department.getEmployees().add(employee);

        departmentDao.save(department);
        employeeDao.save(employee);
    }

    @Test
    @Transactional
    @Rollback(false)
    public void testAdd1(){
        Department department = new Department();
        department.setAddress("南海省");
        department.setPhoneNumber("8888-8888");

        Employee employee = new Employee();
        employee.setGender("男");
        employee.setUserName("小黑");

        /**
         * 配置了员工→部门的关系(多对一的关系)
         *      只发送了两条insert语句
         *  由于配置了员工 → 部门的映射关系(多对一)
         */
        employee.setDepartment(department);

        departmentDao.save(department);
        employeeDao.save(employee);
    }

    @Test
    @Transactional
    @Rollback(false)
    public void testAdd2(){
        Department department = new Department();
        department.setAddress("南海省");
        department.setPhoneNumber("8888-8888");

        Employee employee = new Employee();
        employee.setGender("男");
        employee.setUserName("小黑");

        /**
         * 会有一条多余的语句update
         *      由于一的一方可以委会外键,会发送update语句
         *      解决此问题,只需要在一的一方放弃维护权即可
         *  放弃外键维护权
         *          mappedBy 对方配置关系的属性名称
         */
        department.getEmployees().add(employee);//由于配置了多的一方 → 一的一方的关联关系(当保存的时候,就已经对外键赋值)
        employee.setDepartment(department); //由于配置了 一的一方→ 多的一方的关联关系(发送了一条update语句)

        departmentDao.save(department);
        employeeDao.save(employee);
    }

    /**
     * 级联添加,保存一个部门的同时,保存部门的所有员工
     *      需要在操作主体的实体类上,配置casacde属性
     */
    @Test
    @Transactional
    @Rollback(false)
    public void testCaseCascadeAdd(){
        Department department = new Department();
        department.setAddress("南海省");

        Employee employee = new Employee();
        employee.setUserName("小黑");

        employee.setDepartment(department);
        department.getEmployees().add(employee);

        departmentDao.save(department);
    }

    /**
     * 级联删除
     *      删除部门的同时,删除部门下的所有员工
     */
    @Test
    @Transactional
    @Rollback(false)
    public void testCascadeRemove(){
        //查询部门
        Department department = departmentDao.findOne(1);
        //删除部门
        departmentDao.delete(department);
    }
}
posted @ 2020-08-18 08:51  lawrence林  阅读(325)  评论(0编辑  收藏  举报