Java 如何避免创建多余的实体?

Java 如何避免创建多余的实体?,java,hibernate,jpa,Java,Hibernate,Jpa,在我当前的项目中,我需要执行一些本机查询,从查询中加入的表中选择一些字段,例如: 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

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

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现在抱怨(“uknown entity:result”)类“result”不是一个可能需要将列映射到对象中的实体。 我还尝试在result类中重复
@列
声明


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

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

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

您只需在结果(对象[]列表)上迭代即可生成结果(这是DTO,而不是映射实体):

List rows=(List)query.List();
List-listOfResults=新的ArrayList(rows.size);
对于(对象[]行:行){
添加(新结果((字符串)行[0],(字符串)行[1]);
}

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

org.hibernate.Query query = q.unwrap(org.hibernate.Query.class);
然后设置一个结果转换器:


您可能不需要定义一个视图,该视图返回查询所需的连接列,并使用dataholder类的视图名称。

我可以在DataNucleus JPA中运行该查询(稍作更改),它工作正常,正如JPA规范所规定的那样

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

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

同意。只需添加一个小的(但相当不错的)特性:您可以在JPQL查询中使用NEW操作符,如下所示:从t1 t1 join t1.t2t2中选择NEW com.Result(t1.col1,t2.col5)。如果您有一个Result(String,String)构造函数,它将被调用以创建新的Result对象,而不需要实体本身。是的,我知道,但我觉得很可怕。它不允许重构,只保存两三行琐碎的代码。另外,它使调试变得更加困难。你说的“不允许重构”是什么意思?如果参数或其类型发生更改,则使用或不使用新构造都不会保存您的数据。我认为这是一个权衡的问题,就像Criteria API一样——它对重构更加友好,但就我个人而言,它更难阅读。如果我在构造函数中添加参数,上面的代码将停止编译,我知道我必须修复查询。对于JPQL查询中的new,我将在运行时遇到一个异常。如果我在构造函数中切换参数的顺序,我的IDE将切换所有调用。但如果新的在JPQL中,则不会。如果我的查询返回错误的类型,我将有一个干净的ClassCastException,而不是一些模糊的“找不到构造函数”异常。我将能够检查查询的结果,看看有什么问题。这不是问题所要求的。它要求一个本机查询的解决方案。
org.hibernate.Query query = q.unwrap(org.hibernate.Query.class);
query.setResultTransformer(Transformers.aliasToBean(Result.class));
SELECT t1.col1 AS t1_col1, t2.col5 AS t2_col5 FROM t1 JOIN t2 ON t2.id = t1.t2_id