如何使用Hibernate将SQL查询的结果最好地映射到非实体Java对象?

2022-09-03 01:28:24

我有一个名为X的Hibernate托管Java实体和一个本机SQL函数(myfunc),我从Hibernate SQL查询中调用它,如下所示:

SQLQuery q = hibernateSession.createSQLQuery(
                     "SELECT *, myfunc(:param) as result from X_table_name"
             );

我想做的是将这个查询返回的所有内容映射到一个名为Y的类(不一定由Hibernate管理),Y应该包含X的所有属性/字段加上返回的,例如Y可以扩展类X并添加一个“result”字段。resultmyfunc

我尝试过:

  1. 我尝试过使用,但失败了:q.addEntity(Y.class)org.hibernate.MappingException: Unknown entity com.mycompany.Y
  2. q.setResultTransformer(Transformers.aliasToBean(Y.class));但这失败了:.X 有一个调用了相应 getter 和 setter 的字段,但在本例中,Hibernate 似乎不会将列名 (some_property) 映射到正确的字段名。org.hibernate.PropertyNotFoundException: Could not find setter for some_propertysomeProperty
  3. q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);返回 Map,但值并不总是 X 中相应字段所期望的类型。例如,枚举和日期类型的 X 中的字段不能直接从 SQL 查询返回的 Map 映射(其中它们是字符串)。

处理这种情况的适当方法是什么?


答案 1

请参阅有关 SQL 查询的文档章节

您可以使用该方法来指定 Hibernat 应用于给定列的类型。addScalar()

您可以使用别名将结果与 Bean 属性进行映射:

select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t

或者,(尽管它需要一些代码行,这是我的首选解决方案),您可以自己进行映射:

List<Object[]> rows = query.list();
for (Object[] row : rows) {
    Foo foo = new Foo((Long) row[0], (String) row[1], ...);
}

这样可以避免反射,并让您控制一切。


答案 2

容易。将行转换为 :Map<String, Object>

final org.hibernate.Query q = session.createSQLQuery(sql);
q.setParameter("geo", geo);
q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
final List<Map<String, Object>> src = q.list();
final List<VideoEntry> results = new ArrayList<VideoEntry>(src.size());
for (final Map<String, Object> map:src) {
    final VideoEntry entry = new VideoEntry();
    BeanUtils.populate(entry, map);
    results.add(entry);
}

推荐