Reputation: 2581
First let's say we have two tables. One table is an Employee table with the following columns:
EMPLOYEE: ------------------------ emp_id (int, primary key) emp_name (varchar(125)) emp_dept (foreign key) emp_intro (text)
The other table is a Department table with the following columns:
DEPARTMENT: ----------- dept_id (int, primary key) dept_label (varchar(25))
Here is a sample of the table's values
DEPARTMENT: ------------------------ dept_id | dept_label ------------------------ 1 | Sales ------------------------ 2 | Technology ------------------------ 3 | Finance
In order to return the employee's info with a status label, we need to either perform a JOIN:
SELECT e, d.dept_label FROM employees JOIN department d ON d.dept_id = e.emp_dept
or a multi-table select:
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
However, when using JPA/Hibernate, we need to create two classes:
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;
}
}
Then, there is the repository (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();
}
and lastly, the Java controller that binds the classed query to an endpoint of the application:
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();
}
}
I have already tested this entire structure with only retrieving rows inside of the Employee table (i.e. @Query("SELECT e FROM Employee e") ) and everything returns as is.
MY MAIN ISSUE is how does one return a JOIN QUERY while the query is inside of a specific class (table), being Employee, if I require contents inside of Department?
I've already tried @JoinColumn annotations and that didn't work as well (perhaps I did it wrong).
Any ideas? Thanks.
Upvotes: 0
Views: 15376
Reputation: 32535
You dont have to use raw joins to do that, just use proper relation mapping. Relation between Employee
and Departament
sounds like @ManyToOne
or @ManyToMany
.
You will be able to eg employee.getDepartament()
or query by employee.departament.name=:name
http://www.objectdb.com/api/java/jpa/ManyToMany
You can even map bidirectional relations so you will be able to get deparament from employee, as well as all employees from given deparaments
PS. @JoinColumn
is used to delare DB columnt used for joins it it is different then created by selected named strategies (usualy entityname_id). Actual relation mapping is done by declaring @OneToOne
@OneToMany
@ManyToMany
and those can but doesn't have to be used with @JoinColumn
. It is strict JPA
question.
Here you have complete documentation of JPA 2.1 specification
It describes in details how to declare relations as well as @MappedSuperclass
, inheritance strategies and all other usefull stuff.
Upvotes: 2