【问题标题】:How can I avoid the creation of superfluous entities?如何避免创建多余的实体?
【发布时间】:2011-10-28 09:44:46
【问题描述】:

在我当前的项目中,我需要执行一些本机查询,这些查询从查询​​中加入的表中选择一些字段,例如:

SELECT t1.col1, t2.col5
FROM t1
JOIN t2 ON t2.id = t1.t2_id

我试图将它们存储在像

这样的类中
class Result {
  String t1_col1;
  String t2_col5;
}

使用

Query q = entityManager.createNativeQuery( "THE SQL SELECT" , Result.class );

JPA 现在抱怨(“未知实体:结果”)类“结果”不是将列映射到对象可能需要的实体。 我还尝试在结果类中重复 @Column 声明。

我的问题是如何在不必在我的数据库中创建表示为表的实体的情况下声明这一点?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    唉,我看不到在 JPA 中这样做的方法。但是,您可以使用 hibernate Query 对象来做到这一点。获取它使用:

    org.hibernate.Query query = q.unwrap(org.hibernate.Query.class);
    

    然后设置一个结果转换器。 See here:

    query.setResultTransformer(Transformers.aliasToBean(Result.class));
    

    【讨论】:

      【解决方案2】:

      如果您使用 JPA/Hibernate 执行 SQL 查询,那么您使用了错误的工具。 Hibernate 是一个 ORM,您应该将表映射到实体。这就是 JPA 的全部意义所在。我只想执行 SQL 查询,使用 JDBC(例如 Spring 的 JdbcTemplate)

      一旦 table1 和 table2 映射到实体(我们将这些实体称为 T1 和 T2),您将不再需要这些 SQL 查询,因为 JPQL 只能选择实体的某些字段。您的查询可能如下所示(取决于 t1 和 t2 之间的关联):

      select t1.col1, t2.col5 from T1 t1 join t1.t2 t2
      

      您只需要遍历结果(Object[] 列表)来构建您的结果(这是一个 DTO,而不是映射实体):

      List<Object[]> rows = (List<Object[]>) query.list();
      List<Result> listOfResults = new ArrayList<Result>(rows.size);
      for (Object[] row : rows) {
          listOfResults.add(new Result((String) row[0], (String) row[1]));
      }
      

      【讨论】:

      • 同意。只是添加一个小(但非常好的)功能:您可以在 JPQL 查询中使用 NEW 运算符,如下所示: SELECT NEW com.Result(t1.col1, t2.col5) FROM T1 t1 join t1.t2 t2 如果您有Result(String, String) 构造函数,它将被调用来创建新的 Result 对象,该对象本身不需要是实体。
      • 是的,我知道,但觉得太可怕了。它不允许重构,只节省了两三行琐碎的代码。此外,它使调试变得更加困难。
      • “不允许重构”是什么意思?如果参数或它们的类型发生变化,那么既不使用也不使用 NEW 构造将拯救你。我认为这是一个权衡的问题,就像 Criteria API 一样 - 它对重构更加友好,但对我个人而言,它更难阅读。
      • 如果我向我的构造函数添加一个参数,上面的代码将停止编译,我知道我必须修复查询。使用 JPQL 查询中的 new,我只会在运行时出现异常。如果我在构造函数中切换参数的顺序,我的 IDE 将切换所有调用。但如果新的在 JPQL 中,则不会。如果我的查询返回一些错误的类型,我将有一个干净的 ClassCastException,而不是一些晦涩的“找不到构造函数”异常。我将能够检查查询的结果,看看有什么问题。
      • 这不是问题所要求的。它正在寻求原生查询的解决方案。
      【解决方案3】:

      我可以在 DataNucleus JPA 中运行该查询(稍作更改),它工作正常,因为它应该符合 JPA 规范。

      SELECT t1.col1 AS t1_col1, t2.col5 AS t2_col5 FROM t1 JOIN t2 ON t2.id = t1.t2_id
      

      即使返回列与结果类中的字段名称对齐。 JPA 规范没有说结果类必须是一个实体类;它只是说“结果实例的类”。

      【讨论】:

        【解决方案4】:

        您可能会避免定义一个 VIEW 来返回其查询所需的连接列,并为您的数据持有者类使用视图名称。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-10
          • 1970-01-01
          • 1970-01-01
          • 2021-01-09
          • 1970-01-01
          • 2014-08-17
          • 2016-03-21
          • 1970-01-01
          相关资源
          最近更新 更多