Как наилучшим образом отображать результаты SQL-запроса на объект объекта без объекта с использованием Hibernate?
У меня есть управляемый Java-объект Hibernate под названием X и встроенная функция SQL (myfunc), которую я вызываю из запроса Hibernate SQL по этим строкам:
SQLQuery q = hibernateSession.createSQLQuery(
"SELECT *, myfunc(:param) as result from X_table_name"
);
То, что я хочу сделать, - это сопоставить все, что было возвращено из этого запроса, в класс (не обязательно управляемый Hibernate), который называется Y. Y должен содержать все свойства/поля из X плюс result
, возвращаемые myfunc
, например Y может расширить класс X и добавить поле "результат".
Что я пробовал:
- Я пробовал использовать
q.addEntity(Y.class)
, но это не удалось:
org.hibernate.MappingException: Unknown entity com.mycompany.Y
-
q.setResultTransformer(Transformers.aliasToBean(Y.class));
, но это не удается: org.hibernate.PropertyNotFoundException: Could not find setter for some_property
. X имеет поле под названием someProperty
с соответствующим получателем и установщиком, но в этом случае не похоже, что Hibernate сопоставляет имя столбца (some_property) правильному имени поля.
-
q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
возвращает карту, но значения не всегда относятся к типу, ожидаемому соответствующим полем в X. Например, поля в X типа enum и Date не могут быть сопоставлены непосредственно из Map, возвращаемого SQL-запросом (где это строки).
Каким образом можно справиться с этой ситуацией?
Ответы
Ответ 1
См. главу документации о SQL-запросах.
Вы можете использовать метод addScalar()
, чтобы указать, какой тип Hibernat должен использовать для данного столбца.
И вы можете использовать псевдонимы для сопоставления результатов с помощью свойств 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
Легко
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);
}
Ответ 3
Прежде всего вам нужно объявить сущность в файле конфигурации xibernate конфигурации примерно так:.....
class= "путь к вашей сущности"
Или вы можете сделать то же самое программно, прежде чем делать запрос.