假设我有一个名为 的表,employee其字段为employee_id,name和supervisor_id,
employee_supervisor字段为supervisor_id和name。employee和employee_supervisor表相对于列存在外键关系supervisor_id。
如果我在类中进行多对一注释映射Employee,如何确保 Hibernate 使用 LEFT OUTER JOIN 来连接关联实体?
在我的测试中,Hibernate 默认执行 LEFT OUTER JOIN。但是,您可以确保它将始终使用带注释的 LEFT OUTER JOIN。我花了一些时间使用模板中的双向一对多映射作为基础来模拟您的情况,然后更改类名称以匹配您的情况。
我想出的课程如下:
员工主管类:
@Entity(name="EMPLOYEE_SUPERVISOR")
public class EmployeeSupervisor {
@Id
@GenericGenerator(name = "gen", strategy = "increment")
@GeneratedValue(generator = "gen")
@Column(name = "id")
private int supervisorId;
@Column
private String name;
@OneToMany(mappedBy = "supervisor")
private List<Employee> employees;
....
}
Run Code Online (Sandbox Code Playgroud)
员工类别:
@Entity
public class Employee {
@Id
@GenericGenerator(name = "gen", strategy = "increment")
@GeneratedValue(generator = "gen")
@Column(name = "id")
private int employeeId;
@Column
private String name;
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "supervisorId")
private EmployeeSupervisor supervisor;
....
}
Run Code Online (Sandbox Code Playgroud)
确保你总是使用a的注解LEFT OUTER JOIN就是@Fetch(FetchMode.JOIN注解。这告诉 Hibernate 使用 a 在同一个 select 语句中加载关联的记录LEFT OUTER JOIN(有关其他类型的' 以及每种类型的作用,请参阅文档)。FetchMode
然后我在 jUnit 中模拟了数据库,配置 Hibernate 以在 log4j 中打印所有生成的 SQL
@Entity(name="EMPLOYEE_SUPERVISOR")
public class EmployeeSupervisor {
@Id
@GenericGenerator(name = "gen", strategy = "increment")
@GeneratedValue(generator = "gen")
@Column(name = "id")
private int supervisorId;
@Column
private String name;
@OneToMany(mappedBy = "supervisor")
private List<Employee> employees;
....
}
Run Code Online (Sandbox Code Playgroud)
并运行了一个非常基本的单元测试。
public class EmployeeDAOTest extends SpringTest{
@Autowired
private EmployeeDAO dao;
private Employee testLinkedEmployee;
private Employee testUnlinkedEmployee;
private EmployeeSupervisor testSupervisor;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("Starting DAO Test");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("Finished DAO Test");
}
@Before
public void setUp() throws Exception {
//Irrelevant horrible setup code snipped.
/* Set up 2 employees and a EmployeeSupervisor in the database.
* Link one employee to the EmployeeSupervisor and not the other
*/
}
@Test
@Transactional
public void test() {
Employee actualLinkedEmployee = dao.getEmployee(testLinkedEmployee.getEmployeeId());
Employee actualUnlinkedEmployee = dao.getEmployee(testUnlinkedEmployee.getEmployeeId());
assertNotNull("The linked employee's supervisor didn't get selected.", actualLinkedEmployee.getSupervisor());
assertNull("The unlinked employee's supervisor was not null.", actualUnlinkedEmployee.getSupervisor());
}
}
Run Code Online (Sandbox Code Playgroud)
我的 DAO 非常初级:
@Repository
public class EmployeeDAOImpl implements EmployeeDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public Employee getEmployee(int id) {
Criteria query = sessionFactory.getCurrentSession().createCriteria(Employee.class);
query.add(Restrictions.idEq(id));
return (Employee) query.uniqueResult();
}
}
Run Code Online (Sandbox Code Playgroud)
SQL输出如下:
@Entity
public class Employee {
@Id
@GenericGenerator(name = "gen", strategy = "increment")
@GeneratedValue(generator = "gen")
@Column(name = "id")
private int employeeId;
@Column
private String name;
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "supervisorId")
private EmployeeSupervisor supervisor;
....
}
Run Code Online (Sandbox Code Playgroud)
应该注意的是,默认情况下 Hibernate 似乎急切地获取这些实体并使用 LEFT OUTER JOIN 来执行此操作。但是,如果您尝试将默认获取类型设置为,FetchType.LAZY则联接类型将更改为 a FetchMode.SELECT,并且只为员工发出单个选择,而无需选择主管。
FetchType.LAZY但是,设置@Fetch(FetchMode.JOIN)会覆盖您的延迟获取并使用连接来急切地获取您的主管。
| 归档时间: |
|
| 查看次数: |
22661 次 |
| 最近记录: |