2017-02-22 36 views
1

我有一个由COMPANY_ID通过一对多关系连接的父实体(公司)和子实体(Employee)。公司和员工都有状态栏。休眠子实体条件获取不正确的孩子

CompanyEntity:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "company") 
private List<Employee> employees = new ArrayList<>(); 

@Column(name = "COMPANY_STATUS") 
private String status; 

雇员实体

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "COMPANY_ID", nullable = false) 
private Company company; 

@Column(name = "EMPLOYEE_STATUS") 
private String status; 

现在我需要获取所有的公司(其状态是HIGH_PROFIT或LOW_PROFIT)和员工(谁的地位是永久性的)。我写了一个查询如下。

查询

Criteria criteria = getSession().createCriteria(Company.class); 
    List<String> statusList = new ArrayList<>(); 
    statusList.add("HIGH_PROFIT"); 
    statusList.add("LOW_PROFIT"); 
    criteria.add(Restrictions.in("status", statusList)).createCriteria("employees").add(Restrictions.eq("status", "PERMANENT")); 
    criteria.list(); 

上运行的应用,我得到正确的公司记录,那里的员工不会被永久地位的过滤,它包含与两个合同,并永久地位的所有儿童。

在检查休眠日志,我看到正在执行

1. select this_.id as id1_3_2_, this_.COMPANY_NAME as COMPANY_NAME2_3_2_, this_.COMPANY_STATUS as COMPANY_STATUS3_3_2_, employ1_.id as id1_5_0_, employ1_.EMPLOYEE_STATUS as EMPLOYEE_STA4_5_0_ from COMPANY this_ inner join EMPLOYEE employ1_ on this_.id=employ1_.COMPANY_ID where this_.COMPANY_STATUS in (?, ?) and employ1_.EMPLOYEE_STATUS_ID=? 

2. select employ0_.COMPANY_ID as COMPANY_ID5_5_0_, employ0_.id as id1_5_0_, employ0_.EMPLOYEE_STATUS as EMPLOYEE_STA4_5_1_ from EMPLOYEE employ0_ where employ0_.COMPANY_ID=? 

2个查询我试图对公司实体的雇员使用可变@Fetch(FetchMode.SELECT) @Fetch(FetchMode.JOIN)@Fetch(FetchMode.SUBSELECT)(如下面的代码),毫无效果。

@OneToMany(cascade = CascadeType.ALL, mappedBy = "company") 
    @Fetch(FetchMode.SELECT) 
    private List<Employee> employees = new ArrayList<>(); 

我也尝试过在儿童实体上使用别名,并在孩子身上使用条件。它也没有工作。

有人能帮助我过滤正确的状态吗?

+0

为三带别名的al是否使用过类似[this](http://stackoverflow.com/a/29457393/1910582)? –

+0

是的,我做过。它给了我所有的记录。 – Maz

回答

1

您收到完全正确的结果:

@OneToMany映射不应该在所有的被过滤!

查询转换为下面的句子:取的有“HIGH_PROFIT”和“LOW_PROFIT”和那些至少有一名雇员拥有的地位的所有CompanyEntities状态“永久性”

你拥有的东西像你描述的应该切换无论是服务水平(即List<EmployeeEntity> fetchEmployeeInPermanentState(CompanyEntity entity) { /* write your query on EmployeeEntity here */ }

,或者你可以在你的CompanyEntity类似的东西定义字段:

@Filter(condition = "status = 'PERMANENT'") 
@OneToMany(cascade = CascadeType.ALL, mappedBy = "company") 
private List<Employee> permanentEmployees = new ArrayList<>(); 
+0

不知道我是否明白这一点。我不能在实体中过滤硬编码,因为我需要为不同的条件使用相同的实体。不是吗?在其他一些应用程序中,我也需要获取CONTRACT员工。 – Maz

+0

比您可以定义3个字段更多:所有员工,合同雇员和永久雇员。或者如果你在JAVA8中,你可以创建一个班轮来获取特定种类的员工'临时listEmployee(String type){return employees.stream()。filter(o - > o.status.equals(type))。收集(Collectors.toList()); }' –

+0

这听起来不太有效。我在应用程序的其他地方也有类似的代码,它工作得很好。我在这里做错了事,我无法找到它是什么。 – Maz