17

I have a Hibernate managed Java entity called X and a native SQL function (myfunc) that I call from a Hibernate SQL query along these lines:

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

What I want to do is to map the everything returned from this query to a class (not necessarily managed by Hibernate) called Y. Y should contain all properties/fields from X plus the result returned by myfunc, e.g. Y could extend class X and add a "result" field.

What I've tried:

  1. I've tried using q.addEntity(Y.class) but this fails with: org.hibernate.MappingException: Unknown entity com.mycompany.Y
  2. q.setResultTransformer(Transformers.aliasToBean(Y.class)); but this fails with: org.hibernate.PropertyNotFoundException: Could not find setter for some_property. X has a field called someProperty with the appropriate getter and setter but in this case it doesn't seem like Hibernate maps the column name (some_property) to the correct field name.
  3. q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); returns a Map but the values are not always of the type expected by the corresponding field in X. For example fields in X of type enum and Date cannot be mapped directly from the Map returned by the SQL query (where they are Strings).

What's the appropriate way to deal with this situation?

3 Answers 3

16

See the chapter of the documentation about SQL queries.

You can use the addScalar() method to specify which type Hibernat should use for a given column.

And you can use aliases to map the results with the bean properties:

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

Or, (and although it require some lines of code, it's my preferred solution), you can simply do the mapping yourself:

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

This avoids reflection, and lets you control everything.

Sign up to request clarification or add additional context in comments.

3 Comments

Eek, a cast to Long. How do you know in advance that row[0] is going to be a Long? Is there some way to enforce data type conversion through the Hibernate APIs?
@LukasEder: Follow the link to the documentation, it's explained there. But using SQL queries with Hibernate should be extremely exceptional. Most of the time, you use HQL/criteria queries, and the type is deduced from the type of the field in your entity.
Thanks for the info. I should've completely read your answer... Nonetheless, it's still a bit of a pain that the type info has to be repeated
7

Easy. Cast the rows to 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);
}

1 Comment

Nice idea but works only if database columns are named exactly like the entity fields.
0

First of all you need to declare the entity in the hibernate configuration xml file something like this: ..... class="path to your entity"

Or you can do the same thing programatically before you make the query.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.