J'ai une entité Java gérée par Hibernate appelée X et une fonction SQL native (myfunc) que j'appelle à partir d'une requête SQL Hibernate selon ces lignes:
SQLQuery q = hibernateSession.createSQLQuery(
"SELECT *, myfunc(:param) as result from X_table_name"
);
Ce que je veux faire est de mapper tout ce qui est renvoyé par cette requête à une classe (non nécessairement gérée par Hibernate) appelée Y. Y doit contenir tous les propriétés/champs de X plus la result
renvoyée par myfunc
, par exemple. Y pourrait étendre la classe X et ajouter un champ "résultat".
Ce que j'ai essayé
q.addEntity(Y.class)
mais cela échoue avec: org.hibernate.MappingException: Unknown entity com.mycompany.Y
q.setResultTransformer(Transformers.aliasToBean(Y.class));
mais cela échoue avec: org.hibernate.PropertyNotFoundException: Could not find setter for some_property
. X a un champ appelé someProperty
avec le getter et le setter appropriés, mais dans ce cas, il ne semble pas que Hibernate mappe le nom de la colonne (propriété_quelque_) vers le nom de champ correct.q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
renvoie une mappe mais les valeurs ne sont pas toujours du type attendu par le champ correspondant dans X. Par exemple, les champs dans X de type énuméré et Date ne peuvent pas être mappés directement à partir de la mappe renvoyée par la requête SQL (où ils sont des chaînes).Quelle est la manière appropriée de gérer cette situation?
Voir le chapitre de la documentation sur les requêtes SQL .
Vous pouvez utiliser la méthode addScalar()
pour spécifier le type que Hibernat doit utiliser pour une colonne donnée.
Et vous pouvez utiliser des alias pour mapper les résultats avec les propriétés du bean:
select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t
Ou bien (et bien que cela nécessite quelques lignes de code, c'est ma solution préférée), vous pouvez simplement faire le mappage vous-même:
List<Object[]> rows = query.list();
for (Object[] row : rows) {
Foo foo = new Foo((Long) row[0], (String) row[1], ...);
}
Cela évite la réflexion et vous permet de tout contrôler.
Facile. Convertissez les lignes en 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);
}
Tout d’abord, vous devez déclarer l’entité dans le fichier xml de configuration hibernate, par exemple: ..... Class = "chemin de votre entité"
Ou vous pouvez faire la même chose par programme avant de faire la requête.