【问题标题】:JPA nativeQuery returns cached resultListJPA nativeQuery 返回缓存的结果列表
【发布时间】:2016-04-01 18:04:03
【问题描述】:

我有以下课程:

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 列在 db 中始终为空,并且从未通过 dao 更新,因为对于每个唯一的 Company-Employee 对,还有其他包含 score 的表。 我需要 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;
}

公司道包含方法:

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&lt;Company&gt; 尽管 Hibernate 会在控制台中打印出我的本机查询以及我所做的所有更改,但所有字段都在其位置。 我在这里做错了什么以及如何实现我的需要?谢谢。

【问题讨论】:

  • 如果员工和公司之间已经有双向@ManyToMany,为什么还要使用本机查询从员工ID中检索相关公司?看来您不需要它。
  • 因为分数存储在不同的表中,我需要加入来检索它。还有其他方法吗?
  • 您有一个员工实体,其中包含与该员工相关的公司实体列表:Set 公司;如果您能够通过其 id 找到 Employee 实体,则您已经拥有该 Employee 的相关公司实体。出于这个原因,我不明白您为什么要在公共 Employee get(Long id) {..} 方法中从数据库中检索公司实体列表。
  • 我更改了帖子的文字以使其更清晰。请再读一遍。请注意原生 SQL 查询的文本。它使用 join 将 Company 的 score 字段替换为 Score 的 score 字段。抱歉,我不知道如何进一步提高清晰度。

标签: java mysql hibernate jpa nativequery


【解决方案1】:

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

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

所以你可以尝试使用EntityManager中的refresh方法。

【讨论】:

  • 我认为刷新不起作用,因为它不假设使用自定义本机查询,并且公司的直接表仍然包含 null 分数。再说一遍:目标是用 score.score 代替 company.score,这就是为什么会有原生查询
【解决方案2】:

所以我最终这样做了:

通过查询在 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;
    

    }

这样,我不仅让 score 字段始终保持一致,而且我可以选择一组字段来显示,因为整个 Company 类非常广泛,而且我不需要所有字段来处理这种特殊情况。

【讨论】:

    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    相关资源
    最近更新 更多