Hibernate - original Query exposure.

Asked by another-satisfied-user on 2009-12-03

Would it be possible to extend HQLQuery with a method like getHibernateQuery() with the signature(s) similar to those of HQLQuery.list() ?

This would enable the use of all the original Query API features, like setResultTransformer() etc.

If not possible - maybe integrate setResultTransformer() directly into HQLQuery ?

Anyway - this project looks great! This is what most of the hibernate developers were missing right from the beginning !

Question information

Language:
English Edit question
Status:
Answered
For:
Querydsl Edit question
Assignee:
No assignee Edit question
Last query:
2009-12-04
Last reply:
2009-12-09

Thanks for the suggestion.

Querydsl includes already certain result transformation features such as the constructor projection :

class CustomerDTO {

  @QueryProjection
  public CustomerDTO(long id, String name){
     ...
  }

}

and in the query

QCustomer customer = QCustomer.customer;
HQLQuery query = new HibernateQuery(session);
List<CustomerDTO> dtos = qry.from(customer).list(new QCustomerDTO(customer.id, customer.name));

Providing the internal hibernate query is a bit tricky, because the projection is supplied in the final call, but we can integrate ResultTransformer into the signature.

What is your use case for using ResultTransformer? Do you use it for DTO projections or something else? DTO projections are already supported in Querydsl, but if you can describe another essential use case, we can integrate ResultTransformer.

I made a new release (0.9.0) and added some documentation on the use of constructor projections :

http://source.mysema.com/static/querydsl/0.9.0/reference/html/ch03s02.html#d0e545

Hi Timo,

thank you for the quick answer :)

I guess I've somehow missed the @QueryProjection feature (is it documented anywhere? couldn't find anything - UPDATE: now I see your docu update, wow :)

The @QueryProjection works fine - as it is an equivalent of a "select new (..)" hql syntax. However hql "select new" syntax has some limitations, here is my example, as a side note :

select phrase, phraseTranslation
from Phrase phrase
 inner join fetch phrase.lastModificationAuditTrail
 inner join fetch phrase.creationAuditTrail
 inner join phrase.phraseTranslations as phraseTranslation
 inner join fetch phraseTranslation.request as translationRequest
 inner join fetch translationRequest.lastModificationAuditTrail
 left join fetch phraseTranslation.targetPhrase
order by translationRequest.lastModificationAuditTrail.actionTimestamp desc

works fine, while :

select new PhraseBrowserResult(phrase, phraseTranslation)
from Phrase phrase
 inner join fetch phrase.lastModificationAuditTrail
 inner join fetch phrase.creationAuditTrail
 inner join phrase.phraseTranslations as phraseTranslation
 inner join fetch phraseTranslation.request as translationRequest
 inner join fetch translationRequest.lastModificationAuditTrail
 left join fetch phraseTranslation.targetPhrase
order by translationRequest.lastModificationAuditTrail.actionTimestamp desc

gives the exception :

QueryException : query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=audit_trail,tableAlias=audittrail1_,origin=phrase phrase0_,colums={phrase0_.lastModificationAuditTrail_ID ,className=com.emarson.bizgle.model.domain.AuditTrail}}]

but I dont want to put every fetched association in my constructor (!).

Here comes the ResultTransformer, which doesn't have the restriction as above. Also it is more handy because it doesn't require any code generation from querydsl. Also the AliasToBeanResultTransformer doesn't require you to create a constructor for each set of properties you would like to populate. Last but not least : you can provide your own ResultTransformer implementation which will do what you want.

So I guess that adding a result transformer would be of a great benefit.
How about other Query interface finetuning methods, like cache related etc. ? This is not exposed in HQLQuery either, AFAIK.

BTW. integrating ResultTransformer or another finetuning objects into list() method would result in API bloat - could this be a simple setter just like in the Query API ?

Lukasz.

The problem with providing ResultTransformer as a simple setter is that the ResultTransformer changes the projection :

e.g.

new HibernateQuery(session).from(entity).where(...).setResultTransformer(someTransformer).list(entity);

Here we can't be sure what the type of the projection is, since resulttransformer might change it.

What about providing the original query like this :

HibernateQuery query = new HibernateQuery(session).from(entity).where(...);
org.hibernate.Query origQuery = query.createQuery(entity);
origQuery.setResultTransformer(...);
List results = origQuery.list();

Querydsl's AbstractHibernateQuery provides the following methods :

    private Query createQuery(Expr<?> expr)

    private Query createQuery(Expr<?> expr1, Expr<?> expr2, Expr<?>... rest)

These could be made public. They would be available in HibernateQuery, but not in the HQLQuery interface.

What do you think?

Yes! This is the thing :)
This would enable finetuning the hibernate Query object right before the Query.list() execution - and you will not have to update your API whenever Query API adds any new feature :)

Ok. This will be added in the next release.

great !

btw. Some general thoughts about this project :

1. It seem to be already a fully blown working project with many features, still it is not well known among hibernate community - any reasons ?

2. In the docu you never mention the fantastic feature - ability to build queries with dynamic structure! This way querydsl is not only a replacement of hql but also a replacement for Criteria API (which API is cumbersome to use and limited in functionality). Using querydsl you keep the reference to your HibernateQuery object and you can apply as many joins, wheres etc as you can, in any order, so that you can get a totally mutable hql query without ugly string concatenation. I guess this should be more exposed as a killer-feature (for example with LquidForm you cannot really do that).

3. As I see the only big thing missing is support for subqueries. In hql you can use subqueries in select, from and where clauses. Are you going to introduce subqueries at some point ?

> 1. It seem to be already a fully blown working project with many features, still it is not well known among hibernate community - any reasons ?

Well, it competes with the JPA 2 criteria API, but I believe the dynamic query model of Querydsl is a better approach than the static query model of JPA 2.

Another reason is that lots of people are scared of code generation. LiquidForm has a smaller feature set, but managers without static code generation.

Third reason is that Querydsl is not only for Hibernate, and we approach not only the Hibernate community, so our marketing is not focused on the Hibernate crowd. ;)

> 2. In the docu you never mention the fantastic feature - ability to build queries with dynamic structure! This way querydsl is not only a replacement of hql but also a replacement for Criteria API (which API is cumbersome to use and limited in functionality). Using querydsl you keep the reference to your HibernateQuery object and you can apply as many joins, wheres etc as you can, in any order, so that you can get a totally mutable hql query without ugly string concatenation. I guess this should be more exposed as a killer-feature (for example with LquidForm you cannot really do that).

Yes, we should be more aggressive with the promotion.

> 3. As I see the only big thing missing is support for subqueries. In hql you can use subqueries in select, from and where clauses. Are you going to introduce subqueries at some point ?

Querydsl already supports sub queries. And they are also documented :

http://source.mysema.com/static/querydsl/0.9.0/reference/html/ch02s02.html#d0e404

ad 3.

now I am in heaven :) thanks !!

Query exposure like agreed is now available in version 0.9.1.

Btw, can you given me some kind of summary of your Querydsl experiences? Something like under Usage Experiences on our front page.

I would be very thankful for that!

Can you help with this problem?

Provide an answer of your own, or ask another-satisfied-user for more information if necessary.

To post a message you must log in.