休眠获取模式加入不工作
Hibernate Fetch Mode Join Not working
我试图在 Hibernate 中使用 FetchMode.JOIN 来理解但面临某些问题。
我有 3 classes Department、Employee 和 EmployeeMain Class。 Department 与 Employee 有一对多的关系。
下面是代码
部门 Class :-
@Entity
@Table(name="DEPARTMENT")
public class Department {
@Id
@GeneratedValue
@Column(name="DEPARTMENT_ID")
private Long departmentId;
@Column(name="DEPT_NAME")
private String departmentName;
@OneToMany(mappedBy="department")
@Fetch(FetchMode.JOIN)
private List<Employee> employees = new ArrayList<>();
public Long getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Long departmentId) {
this.departmentId = departmentId;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
员工class:-
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
private Date birthDate;
@Column(name="cell_phone")
private String cellphone;
@ManyToOne
@JoinColumn(name="department_id")
private Department department;
public Employee() {
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Employee(String firstname, String lastname, String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = new Date(System.currentTimeMillis());
this.cellphone = phone;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
}
主要 Class :-
public class EmployeeMain {
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure("hibernate.xml").buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
Department department1 = new Department();
department1.setDepartmentName("Sales");
session.save(department1);
Department department2 = new Department();
department2.setDepartmentName("Operations");
session.save(department2);
Employee emp1 = new Employee("Nina", "Mayers", "111");
Employee emp2 = new Employee("Tony", "Almeida", "222");
Employee emp3 = new Employee("Rina", "Coyeet", "333");
Employee emp4 = new Employee("Mary", "Land", "444");
emp1.setDepartment(department1);
emp2.setDepartment(department1);
emp3.setDepartment(department2);
emp4.setDepartment(department2);
department1.setEmployees(new ArrayList<Employee>());
department1.getEmployees().add(emp1);
department1.getEmployees().add(emp2);
department2.getEmployees().add(emp3);
department2.getEmployees().add(emp4);
session.save(emp1);
session.save(emp2);
session.save(emp3);
session.save(emp4);
session.getTransaction().commit();
session.close();
session = sessionFactory.openSession();
session.beginTransaction();
List<Department> departmentList = session.createQuery("from Department").list();
for(Department department : departmentList){
department.getEmployees();
}
}
}
我在每个部门下插入了 2 个部门和 2 个员工。
即使在 Department class 中我提到了 @Fetch(FetchMode.JOIN) for employees object 仍然对 Employees 的查询是 运行 twice on each department 。如果我提到正确的话,基本上就是 N+1 select 问题。但是根据我的说法,如果 FetchMode 是 Join 那么一个查询将被触发加入 Employee 和 department 并且应该已经获取数据。
但是以下查询被解雇了。
查询 1
Hibernate: select department0_.DEPARTMENT_ID as DEPARTME1_0_, department0_.DEPT_NAME as DEPT_NAM2_0_ from DEPARTMENT department0_
查询 2
Hibernate: select employees0_.department_id as departme6_0_0_, employees0_.employee_id as employee1_1_0_, employees0_.employee_id as employee1_1_1_, employees0_.birth_date as birth_da2_1_1_, employees0_.cell_phone as cell_pho3_1_1_, employees0_.department_id as departme6_1_1_, employees0_.firstname as firstnam4_1_1_, employees0_.lastname as lastname5_1_1_ from EMPLOYEE employees0_ where employees0_.department_id=?
查询 3
Hibernate: select employees0_.department_id as departme6_0_0_, employees0_.employee_id as employee1_1_0_, employees0_.employee_id as employee1_1_1_, employees0_.birth_date as birth_da2_1_1_, employees0_.cell_phone as cell_pho3_1_1_, employees0_.department_id as departme6_1_1_, employees0_.firstname as firstnam4_1_1_, employees0_.lastname as lastname5_1_1_ from EMPLOYEE employees0_ where employees0_.department_id=?
HQL 查询不获取基于注释的关联。要实现此目标,您必须在 HQL 查询中指定获取策略:
from Department d inner join fetch d.employees
我试图在 Hibernate 中使用 FetchMode.JOIN 来理解但面临某些问题。 我有 3 classes Department、Employee 和 EmployeeMain Class。 Department 与 Employee 有一对多的关系。
下面是代码 部门 Class :-
@Entity
@Table(name="DEPARTMENT")
public class Department {
@Id
@GeneratedValue
@Column(name="DEPARTMENT_ID")
private Long departmentId;
@Column(name="DEPT_NAME")
private String departmentName;
@OneToMany(mappedBy="department")
@Fetch(FetchMode.JOIN)
private List<Employee> employees = new ArrayList<>();
public Long getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Long departmentId) {
this.departmentId = departmentId;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
员工class:-
@Entity
@Table(name="EMPLOYEE")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
private Date birthDate;
@Column(name="cell_phone")
private String cellphone;
@ManyToOne
@JoinColumn(name="department_id")
private Department department;
public Employee() {
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Employee(String firstname, String lastname, String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = new Date(System.currentTimeMillis());
this.cellphone = phone;
}
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
}
主要 Class :-
public class EmployeeMain {
public static void main(String[] args) {
SessionFactory sessionFactory = new Configuration().configure("hibernate.xml").buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
Department department1 = new Department();
department1.setDepartmentName("Sales");
session.save(department1);
Department department2 = new Department();
department2.setDepartmentName("Operations");
session.save(department2);
Employee emp1 = new Employee("Nina", "Mayers", "111");
Employee emp2 = new Employee("Tony", "Almeida", "222");
Employee emp3 = new Employee("Rina", "Coyeet", "333");
Employee emp4 = new Employee("Mary", "Land", "444");
emp1.setDepartment(department1);
emp2.setDepartment(department1);
emp3.setDepartment(department2);
emp4.setDepartment(department2);
department1.setEmployees(new ArrayList<Employee>());
department1.getEmployees().add(emp1);
department1.getEmployees().add(emp2);
department2.getEmployees().add(emp3);
department2.getEmployees().add(emp4);
session.save(emp1);
session.save(emp2);
session.save(emp3);
session.save(emp4);
session.getTransaction().commit();
session.close();
session = sessionFactory.openSession();
session.beginTransaction();
List<Department> departmentList = session.createQuery("from Department").list();
for(Department department : departmentList){
department.getEmployees();
}
}
}
我在每个部门下插入了 2 个部门和 2 个员工。 即使在 Department class 中我提到了 @Fetch(FetchMode.JOIN) for employees object 仍然对 Employees 的查询是 运行 twice on each department 。如果我提到正确的话,基本上就是 N+1 select 问题。但是根据我的说法,如果 FetchMode 是 Join 那么一个查询将被触发加入 Employee 和 department 并且应该已经获取数据。 但是以下查询被解雇了。 查询 1
Hibernate: select department0_.DEPARTMENT_ID as DEPARTME1_0_, department0_.DEPT_NAME as DEPT_NAM2_0_ from DEPARTMENT department0_
查询 2
Hibernate: select employees0_.department_id as departme6_0_0_, employees0_.employee_id as employee1_1_0_, employees0_.employee_id as employee1_1_1_, employees0_.birth_date as birth_da2_1_1_, employees0_.cell_phone as cell_pho3_1_1_, employees0_.department_id as departme6_1_1_, employees0_.firstname as firstnam4_1_1_, employees0_.lastname as lastname5_1_1_ from EMPLOYEE employees0_ where employees0_.department_id=?
查询 3
Hibernate: select employees0_.department_id as departme6_0_0_, employees0_.employee_id as employee1_1_0_, employees0_.employee_id as employee1_1_1_, employees0_.birth_date as birth_da2_1_1_, employees0_.cell_phone as cell_pho3_1_1_, employees0_.department_id as departme6_1_1_, employees0_.firstname as firstnam4_1_1_, employees0_.lastname as lastname5_1_1_ from EMPLOYEE employees0_ where employees0_.department_id=?
HQL 查询不获取基于注释的关联。要实现此目标,您必须在 HQL 查询中指定获取策略:
from Department d inner join fetch d.employees