JPA nativeQuery返回缓存的resultList

时间:2015-12-27 19:49:43

标签: java mysql hibernate jpa nativequery

我有以下课程:

Company.class:

public class Company {
    @JoinTable(name = "company_employee", joinColumns = @JoinColumn(name = "company_id") , inverseJoinColumns = @JoinColumn(name = "employee_id") )
    @ManyToMany(fetch = FetchType.LAZY)
    private Set<Employee> employees;

    @Column(name = "score")
    private BigDecimal score;
}

和Employee.class

public class Employee {
         @ManyToMany(fetch = FetchType.EAGER, mappedBy="employees")
         private Set<Company> companies;
}

公司的分数列在数据库中始终为空,并且从不通过dao更新,因为还有其他表包含每个唯一对Company-Employee的分数。 我需要Score的值,仅适用于我通过id获取Employee的情况,因此这种情况下Set中的所有公司实例都应包含得分,因此我将获得Employee-Company得分对,其中员工获取Employee。 我有以下代码来实现:

public Employee get(Long id) {
    Employee emp = (Employee) dao.find(id);
    List<Company> compList = compnanyService.getByEmpId(id);
    Set<Company> compSet = new HashSet<Company>(compList);
    emp.setCompanies(compSet);
    return emp;
}

公司Dao包含方法:

public List<Company> getByEmpId(Long id) {
        final Query query = this.entityManager.createNativeQuery("select company.comp_id, ...some other fields, score.score from company join score on company.company_id=score.company_id where score.employee_id=:employee_id",
                Company.class);
        query.setParameter("employee_id", id);
        List<Company> comps = query.getResultList();
        return comps;
}

问题是getByEmpId(id)给出ResultList company.score,其中List<Company>为空虽然在db中执行但它不为空。

我怀疑有一些缓存介入,所以我尝试从本机查询中删除一些列,它应该在映射时调用“没有找到列”(或相似)消息的异常,但是这种方法仍然给出了虽然Hibernate在控制台中打印出我的本机查询,并且我做了所有更改,但\[ContestPool\] 包含所有字段。 我在这里做错了什么以及如何实现我的需求?谢谢。

2 个答案:

答案 0 :(得分:1)

它可能与第一级缓存相关联,在使用本机SQL查询时可能会不同步。来自here

  

如果您绕过JPA并直接在数据库上执行DML   通过本机SQL查询,JDBC或JPQL UPDATE或DELETE查询,   那么数据库可能与第一级缓存不同步。如果你   在执行DML之前访问过对象,它们将具有旧的   状态,不包括更改。取决于你在做什么   这可能没问题,否则您可能想要刷新受影响的对象   来自数据库。

因此,您可以尝试使用refresh中的EntityManager方法。

答案 1 :(得分:0)

所以我最终这样做了:

从查询中创建db中的视图:

  1. CREATE VIEW companyscore AS select company.comp_id, score.emp_id ...some other fields, score.score from company join score on company.comp_id=score.comp_id;

  2. 创建了对应的实体CompanyScore,其复合主要ID为comp_id和emp_id,并将视图创建为表格。

  3. 将员工实体更改为:

    公共类员工{

        @OneToMany(fetch = FetchType.EAGER) 
        @JoinColumn(name = "emp_id")
         private Set<CompanyScore> companies;
    

    }

  4. 这样我不仅可以将得分字段保持一致,而且我可以选择要显示的字段集,因为整个公司类非常广泛,并且我不需要这个特定情况的所有字段。