如何在Spring Data JPA中关联表返回type_name而非type_id
实现步骤
1. 创建EmployeeType实体类
首先为employeetype表创建对应的JPA实体,映射表字段并定义主键:
@Entity @Table(name = "employeetype") public class EmployeeType { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "type_name") private String typeName; // 生成无参、全参构造方法,以及getter/setter }
2. 修改Employee实体类,建立关联关系
替换原有的typeId字段,用@ManyToOne注解建立与EmployeeType的多对一关联,映射两张表的外键关系:
@Entity @Table(name = "employee") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="emp_id") private Long id; @Column(name="emp_name") private String empName; @Column(name="emp_mail") private String empMail; @Column(name="emp_no") private String empNo; @Column(name="emp_salary") private Long empSalary; // 替换原typeId字段,建立多对一关联 @ManyToOne(fetch = FetchType.LAZY) // 根据业务需求选择懒加载(LAZY)或急加载(EAGER) @JoinColumn(name = "type_id", referencedColumnName = "id") private EmployeeType employeeType; // 生成getter/setter,通过getEmployeeType()可获取类型对象,进而得到typeName }
3. 三种方式返回包含type_name的结果
方式一:使用DTO对象映射结果
创建一个DTO类,封装需要返回的字段:
public class EmployeeDTO { private Long id; private String empName; private String empMail; private String empNo; private Long empSalary; private String typeName; // 全参构造方法 public EmployeeDTO(Long id, String empName, String empMail, String empNo, Long empSalary, String typeName) { this.id = id; this.empName = empName; this.empMail = empMail; this.empNo = empNo; this.empSalary = empSalary; this.typeName = typeName; } // 生成getter方法 }
在JpaRepository中编写JPQL查询,直接构造DTO返回:
public interface EmployeeRepository extends JpaRepository<Employee, Long> { @Query("SELECT new com.yourpackage.dto.EmployeeDTO(e.id, e.empName, e.empMail, e.empNo, e.empSalary, et.typeName) " + "FROM Employee e JOIN e.employeeType et") List<EmployeeDTO> findAllWithTypeName(); }
方式二:使用Spring Data投影(Projection)
创建一个投影接口,定义需要返回的属性方法:
public interface EmployeeProjection { Long getId(); String getEmpName(); String getEmpMail(); String getEmpNo(); Long getEmpSalary(); // 遵循嵌套属性访问规则:employeeType是Employee的属性,typeName是EmployeeType的属性 String getEmployeeTypeTypeName(); }
在Repository中直接调用投影查询方法:
public interface EmployeeRepository extends JpaRepository<Employee, Long> { List<EmployeeProjection> findAllProjectedBy(); }
方式三:原生SQL查询(不修改实体关联时使用)
如果不想修改原Employee实体的字段,可直接用原生SQL关联查询:
public interface EmployeeRepository extends JpaRepository<Employee, Long> { @Query(value = "SELECT e.emp_id AS id, e.emp_name AS empName, e.emp_mail AS empMail, e.emp_no AS empNo, " + "e.emp_salary AS empSalary, et.type_name AS typeName " + "FROM employee e JOIN employeetype et ON e.type_id = et.id", nativeQuery = true) List<EmployeeDTO> findAllWithTypeNameNative(); }
注意事项
- 关联的
fetch策略:LAZY懒加载会在首次访问employeeType属性时才执行关联查询,适合不频繁需要类型名称的场景;EAGER急加载会在查询Employee时同时查询关联的EmployeeType,适合每次都需要类型名称的场景,但要注意避免N+1查询问题。 - DTO方式灵活性更高,适合复杂字段组合;投影方式更简洁,适合简单的字段提取场景。
内容的提问来源于stack exchange,提问作者Subash
相关产品推荐
相关产品推荐

