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

Joh*_*han 17 java hibernate hibernate-mapping

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

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

我想要做的是将从此查询返回的所有内容映射到一个名为Y的类(不一定由Hibernate管理).Y应该包含来自X的所有属性/字段加上result返回的myfunc,例如Y可以扩展类X并添加一个"结果"字段.

我尝试过的:

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

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

JB *_*zet 16

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

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

您可以使用别名将结果映射到bean属性:

select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • Eek,演员为'Long`.你怎么知道`row [0]`将是一个'Long`?有没有办法通过Hibernate API实施数据类型转换? (2认同)

Sta*_*lov 7

简单.将行转换为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);
}
Run Code Online (Sandbox Code Playgroud)