【发布时间】:2020-01-06 16:11:02
【问题描述】:
我有一个复杂的 Oracle 查询,为了简单起见,它看起来像这样;
SQL> SELECT d.id AS dept_id,
2 d.name AS dept_name,
3 e.id AS emp_id,
4 e.name AS emp_name,
5 e.dept_id AS emp_dept_id
6 FROM drs2_dept d, drs2_emp e
7 WHERE d.id = e.dept_id (+)
8 /
DEPT_ID DEPT_NAME EMP_ID EMP_NAME EMP_DEPT_ID
---------- ------------------- ---------- -------------- -----------
1 SALES 101 JOHN 1
1 SALES 102 JANE 1
2 ADMIN
我的Department 班级是;
@SqlResultSetMapping(
name = "Department.employeeMapping",
classes = {
@ConstructorResult(
targetClass = Department.class,
columns = {
@ColumnResult(name = "DEPT_ID", type = Integer.class),
@ColumnResult(name = "DEPT_NAME")
}
),
@ConstructorResult(
targetClass = Employee.class,
columns = {
@ColumnResult(name = "EMP_ID", type = Integer.class),
@ColumnResult(name = "EMP_NAME"),
@ColumnResult(name = "EMP_DEPT_ID", type = Integer.class)
}
)
}
)
@NamedNativeQuery(
name = "Department.findAllEmployees",
query = "SELECT d.id AS dept_id, " +
" d.name AS dept_name, " +
" e.id AS emp_id, " +
" e.name AS emp_name " +
" e.dept_id AS emp_dept_id, " +
"FROM drs2_dept d, drs2_emp e " +
"WHERE d.id = e.dept_id (+)",
resultSetMapping = "Department.employeeMapping"
)
@Entity
public class Department {
@Id // JPA will not start without it.
Integer id;
String name;
@OneToMany // JPA will not start without it.
List<Employee> employees = new ArrayList<>();
public Department(Integer id, String name) {
this.id = id;
this.name = name;
}
public Department() {}
// getters and setters
}
我的Employee 班级是;
@Entity
public class Employee {
@Id Integer id;
Integer departmentId;
String name;
public Employee(Integer id, String name, Integer departmentId) {
this.id = id;
this.name = name;
this.departmentId = departmentId;
}
public Employee() {}
// getters and setters
}
因为我使用的是@ConstructorResult,所以我可以得到数据,但它仍然是一个扁平结构,也就是说一个List<Object[]>有三个条目,每个条目都包含[Department, Employee]。所以我必须执行以下操作才能将Employee 记录移动到各自的Department 中;
@Component
public class DepartmentDAO {
@PersistenceContext EntityManager entityManager;
public Collection<Department> getAllDepartments() {
Query query = entityManager.createNamedQuery("Department.findAllEmployees");
Map<Integer, Department> map = new HashMap<>();
List<Object[]> list = query.getResultList();
for (Object[] tuple: list) {
Department d = (Department) tuple[0];
if (! map.containsKey(d.getId())) {
map.put(d.getId(), d);
}
d = map.get(d.getId());
Employee e = (Employee) tuple[1];
if (e.getId() != null) {
d.getEmployees().add(e);
}
}
return map.values();
}
}
每当我向@OneToMany 添加任何其他属性时,我似乎都会在 Hibernate 日志中生成不正确的虚假 SQL(即不存在的列或表名),但正如我在此问题开头所述,我只想要本机 SQL - 我不希望 Hibernate 弄清楚我想要做什么。
有没有办法让 JPA/Hibernate 将 Employee 对象放入 Department 的列表中?
( 作为子注释,我在这里看到过这个问题,但在 2011 年之前从未回答或回答过,那时 JPA 和 Hibernate 可能已经取得了进展。
我还应该补充一点,在我的项目的其他地方,我已经将 Department 和 Employee 完全映射为 CrudRepository 与 @Table 和 @Column 一起使用,但是他们的 @OneToMany 定义并不能描述我的身份在上面的查询中做,因此在我的示例代码中没有它们。
)
【问题讨论】:
-
您能找到任何解决方案吗?我正在寻找相同的解决方案。
-
@user2723039 我没有找到解决方案。我使用的是 Spring,所以最终使用了 RowMapper。因此我失去了对“@Table”和“@Column”的好处
标签: jpa spring-data-jpa jpa-2.0 jpa-2.1