Spring Data JPA -- 多表操作(一對多)

前言

在實際的開發中,一對多是家常便飯。舉個栗子,比如一個部門,在部門裏麪包含了多個員工,其中,部門就是一,而員工當然就是多。接下來就以這個栗子進行開發。

以下是我所用到的表數據:

表employee: 

表department:

 1.新建兩個實體類

Employee類:

package com.chen.domain.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Getter
@Setter
@Entity
@Table(name = "test_employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private int age;

    @ManyToOne(targetEntity = Department.class)
    @JoinColumn(name = "dept_id",referencedColumnName = "id")
    private Department department;
}

說明:因爲Employee是屬於多的關係,那麼我們就需要用到@ManyToOne(targetEntity = Department.class),代表多對一,配置級聯關係,然後使用@JoinColumn(name = "dept_id",referencedColumnName = "id")配置兩個表之間的映射關係,其中name = "dept_id"表示外鍵名稱,referencedColumnName = "id"表示該外鍵與Department類的id屬性關聯。

Department類:

package com.chen.domain.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Getter
@Setter
@Entity
@Table(name = "test_department")
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "name")
    private String name;

}

2.新建dao層接口

package com.chen.dao;

import com.chen.domain.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Integer>, JpaSpecificationExecutor<Employee> {

    @Query(value = "SELECT e.name,e.age,d.name AS department FROM test_employee e LEFT JOIN test_department d on e.dept_id=d.id ",nativeQuery = true)
    List<Map<String,Object>> findAllEmployee();
}

3.新建service層,用來實現dao層接口中的方法

package com.chen.service;

import com.chen.dao.EmployeeRepository;
import com.chen.domain.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    public List<Employee> findAll(){
        return employeeRepository.findAll();
    }

    public List<Map<String, Object>> findAllEmployee(){
        return employeeRepository.findAllEmployee();
    }
}

4.使用controller進行業務調用

package com.chen.controller;

import com.chen.domain.entity.Employee;
import com.chen.restful.RestResponse;
import com.chen.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @PostMapping("findAll")
    public RestResponse findAll(){
        List<Employee> allEmployee = employeeService.findAll();
        return RestResponse.ok().data(allEmployee);
    }

    @PostMapping("findAllEmployee")
    public RestResponse findAllEmployee(){
        List<Map<String, Object>> allEmployee = employeeService.findAllEmployee();
        return RestResponse.ok().data(allEmployee);
    }

}

5.測試

第一個先測試JPA中自帶的方法:

接下來測試自己定義的方法:

6.放棄外鍵

一般在項目中,是不會在表中建立外鍵,原因有很多,比如影響效率或因爲外鍵級聯的關係導致增刪改出現問題,我的做法是直接放棄外鍵,就是在表與表之間不設立外鍵關係,當然,還是要配標識來進行關聯。目前不清楚這種做法是否是合理的,但經過我自己測試,是完全可用,且不會出現問題。這樣一來的話,便可以省去很多不必要的操作,就連非常複雜的多表操作也可以輕易實現。

接下來我把Employee表中的外鍵配置去掉,換成一個普通的字段:

package com.chen.domain.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Getter
@Setter
@Entity
@Table(name = "test_employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private int age;

    @Column(name = "dept_id")
    private int deptId;

    //@ManyToOne(targetEntity = Department.class)
    //@JoinColumn(name = "dept_id",referencedColumnName = "id")
    //private Department department;
}

然後同樣進行請求測試:

可以發現,結果跟設了外鍵級聯的結果一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章