【问题标题】:Spring/JPA/Hibernate How to Perform Join of Two Entities In One RepositorySpring/JPA/Hibernate 如何在一个存储库中执行两个实体的联接
【发布时间】:2017-10-10 20:59:23
【问题描述】:

首先假设我们有两张桌子。一个表是具有以下列的 Employee 表:

员工: ---------------------- emp_id (int, 主键) emp_name (varchar(125)) emp_dept(外键) emp_intro(文本)

另一个表是Department表,包含以下列:

部: ------------ dept_id (int, 主键) 部门标签(varchar(25))

这是表格值的示例

部: ---------------------- 部门 ID |部门标签 ---------------------- 1 |销售量 ---------------------- 2 |技术 ---------------------- 3 |金融

为了返回带有状态标签的员工信息,我们需要执行 JOIN:

SELECT e, d.dept_label FROM employees JOIN department d ON d.dept_id = e.emp_dept

或多表选择:

SELECT e.emp_id, e.emp_name, d.dept_label, e.emp_intro FROM employees e, department d WHERE e.emp_dept = d.dept_id

但是,当使用 JPA/Hibernate 时,我们需要创建两个类:

Employee.java

package com.example.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "employees")
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "emp_id")
    private long emp_id;

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

    @Column(name = "emp_dept")
    private Integer emp_dept;

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

    public long getEmp_id() {
        return emp_id;
    }

    public void setEmp_id(long emp_id) {
        this.emp_id = emp_id;
    }

    public String getEmp_name() {
        return emp_name;
    }

    public void setEmp_name(String emp_name) {
        this.emp_name = emp_name;
    }

    public Integer getEmp_dept() {
        return emp_dept;
    }

    public void setEmp_dept(Integer emp_dept) {
        this.emp_dept = emp_dept;
    }

    public String getEmp_intro() {
        return emp_intro;
    }

    public void setEmp_intro(String emp_intro) {
        this.emp_intro = emp_intro;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

}

Department.java

package com.example.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "departments")
public class Department implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "dept_id")
    private long dept_id;

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

    public long getDept_id() {
        return dept_id;
    }

    public void setDept_id(long dept_id) {
        this.dept_id = dept_id;
    }

    public String getDept_label() {
        return dept_label;
    }

    public void setDept_label(String dept_label) {
        this.dept_label = dept_label;
    }

    public static long getSerialversionuid() {
        return serialVersionUID;
    }

}

然后是存储库(DAO):

EmployeeRepository

package com.example.repository;

import.java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.example.entities.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {

    @Query("select e, d.dept_label FROM Employee e JOIN Department d ON "
    + "d.dept_id = e.emp_id")
    public List<Employee> return getEmployees();

}

最后,将分类查询绑定到应用程序端点的 Java 控制器:

EmployeeController.java

package com.example.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.entities.Department;
import com.example.entities.Employee;
import com.example.repository.EmployeeRepository;

@Controller
public class EmployeeController {

    @Autowired
    EmployeeRepository er;

    @RequestMapping(value = "/getEmployees")
    public @ResponseBody List<Employee> getEmployees() {
        return er.getEmployees();
    }

}

我已经测试了整个结构,只检索 Employee 表中的行(即 @Query("SELECT e FROM Employee e") )并且一切都按原样返回。

我的主要问题是,如果我需要部门内的内容,当查询位于特定类(表)(即员工)内部时,如何返回 JOIN QUERY?

我已经尝试过 @JoinColumn 注释,但效果不佳(也许我做错了)。

有什么想法吗?谢谢。

【问题讨论】:

  • 面向对象的语言允许对象引用形成对象之间的关系。你没有这些。关系不是很长,恰好代表其他类的某个对象,它应该是一个对象引用!那是在 O-O 级别,甚至不是 JPA 级别

标签: java hibernate jpa


【解决方案1】:

您不必使用原始连接来执行此操作,只需使用适当的关系映射即可。 EmployeeDepartament 之间的关系听起来像 @ManyToOne@ManyToMany。 您将可以通过employee.getDepartament()employee.departament.name=:name 查询

http://www.objectdb.com/api/java/jpa/ManyToMany

您甚至可以映射双向关系,以便您能够从员工那里获得部门,以及来自给定部门的所有员工

PS。 @JoinColumn 用于删除用于连接的 DB 列,它与由选定的命名策略(通常是 entityname_id)创建的不同。实际的关系映射是通过声明 @OneToOne @OneToMany @ManyToMany 来完成的,这些可以但不必与 @JoinColumn 一起使用。这是严格的JPA 问题。

Here you have complete documentation of JPA 2.1 specification 它详细描述了如何声明关系以及@MappedSuperclass、继承策略和所有其他有用的东西。

【讨论】:

  • 我实际上遵循了 JPA 2.1 规范的 JPA 文档:根据文档,Department 类中不需要注释。我想使用Department.label属性,所以必须加@OneToOne单向。我添加了三行:1)private Department 2)@OneToOne 注释,3)该行下的 getter 和 4)该行下的 setter。然后我收到一个“无效的列名“部门”错误。任何想法? (
  • @MindsectTeam 更新问题以反映您的变化
  • 我已经做出了反思性的改变。
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-21
  • 2015-05-14
  • 2013-11-27
  • 1970-01-01
相关资源
最近更新 更多