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

然后同样进行请求测试:

可以发现,结果跟设了外键级联的结果一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西瓜不甜柠檬不酸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值