JPA nativeQuery returns 缓存的结果列表

JPA nativeQuery returns cached resultList

我关注类:

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;
}

Company 的 Score 列在数据库中始终为 null,并且永远不会通过 dao 更新,因为还有其他 table 包含每个唯一对 Company-Employee 的分数。 我需要 Score 的值,仅适用于我通过 id 获取 Employee 的情况,因此这种情况下 Set 中的所有 Company 实例都应包含 score,因此我将获得 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;
}

Company 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 是空的,尽管在数据库中执行它不是空的。

我怀疑有一些缓存干预,所以我尝试从本机查询中删除一些列,它应该在映射时调用带有 "no column found"(或类似)消息的异常,但是这个方法尽管 Hibernate 在控制台中打印出我的本机查询以及我所做的所有更改,但仍会在其位置上提供所有字段的 List<Company> 。 我在这里做错了什么以及如何实现我的需要?谢谢。

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

If you bypass JPA and execute DML directly on the database, either through native SQL queries, JDBC, or JPQL UPDATE or DELETE queries, then the database can be out of synch with the 1st level cache. If you had accessed objects before executing the DML, they will have the old state and not include the changes. Depending on what you are doing this may be ok, otherwise you may want to refresh the affected objects from the database.

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

所以我最终这样做了:

根据查询在数据库中创建了视图:

  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,并创建了视图为 table。

  3. 已将员工实体更改为:

    public class 员工 {

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

    }

这样我不仅可以让分数字段始终保持一致,而且我可以选择一组字段来显示整个公司 class 相当广泛,我不需要这个特定案例的所有字段.