-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: How to map results of a SQL query
PostPosted: Wed Dec 02, 2009 1:32 pm 
Regular
Regular

Joined: Tue Oct 10, 2006 2:21 pm
Posts: 58
I wish to execute a query containing an outer join of two not-really-related tables. By "not-really-related" I mean that there is a many-to-many relationship between two tables in which there may or may not be a coincidental match between two columns. (A user may match 0-to-many Speed Dial names to a Telephone Number and may make any number calls to numbers that happen to be referenced to 0 or more speed dial entries). As such, my inclination is to avoid expressing any relationship between the two tables in my Hibernate mapping files - no such relationship is maintained in the database.

I looked into writing such a query in HQL. In HQL, according to "Java Persistence with Hibernate", all the join styles except "Theta-style joins" (pp 652-653) seem to imply mapping relationships. However, p.653 gives me the bad news that "it's currently not possible in HQL or JPA QL to outer join two tables that don't have a mapped association -- theta style joins are inner joins". So if this is correct, HQL is a non-starter for my purposes.

I next looked into a SQL query. I created such a query that performs the outer join I need and it works. I am pretty sure I could implement this as a projection and mess around by hand with the result sets, but I would rather have the result set objects be mapped to POJOs by Hibernate if possible.

How can I map them, though? Mapping as a class demands that I define an ID and there really isn't one. These objects will simply be presented to the user and go away. They will never be persisted. I don't see an ID generator that fits such an oddball use case. The best I have been able to come up with so far is to grab the primary key for the main class in the outer join even though I don't actually need it and call that the id.

I come up with the following:
Code:
  <class name="CallHistoryRecord" >
    <id type="integer" column="CallStatID" /> 
    <!-- note, no name, won't show up in POJO, where it isn't needed -->
  </class>
- <sql-query name="getCallHistory" >
-   <return alias="call" class="CallHistoryRecord">
      <return-property name="name" column="Name" />
      <return-property name="phoneNumber" column="PhoneNumber" />
      <return-property name="when" column="CallStartDateTime" />
      <return-property name="direction" column="Direction" />
    </return>

    SELECT
      c.CallStatID,
      c.PhoneNumber AS PhoneNumber,
      c.CallStartDateTime as CallStartDateTime,
      c.Direction as Direction,
      MAX(s.SpeedDialName) AS Name
    FROM
      CallStats c
      LEFT OUTER JOIN SpeedDials s
        ON s.UserID=c.UserID
        AND s.PhoneNumber=c.PhoneNumber
    WHERE c.UserID=:id
    GROUP BY 1,2,3,4
    ORDER BY 3 DESC 
  </sql-query>


But when I call this query (against a MySQL 5.0 database), I get the following error.

"Column 'CallStatID24_0_' not found"

As I stated, the sql query works standalone. Why is Hibernate looking for "CallStatID24_0_" rather than just "CallStatID" and how do I get around this? OR, is there a better strategy for doing this that I've completely overlooked here?


Top
 Profile  
 
 Post subject: Re: How to map results of a SQL query
PostPosted: Wed Dec 02, 2009 4:01 pm 
Regular
Regular

Joined: Tue Oct 10, 2006 2:21 pm
Posts: 58
I have found a way to get beyond this. It's not perfectly ideal but it's close.

That way is to abandon any attempt to map the <return> elements in the query:

Code:
   <sql-query name="getCallHistory">
      SELECT
         c.PhoneNumber AS phoneNumber,
         c.CallStartDateTime as timeCallBegan,
         c.Direction as direction,
         MAX(s.SpeedDialName) AS name
      FROM CallStats c
      LEFT OUTER JOIN SpeedDials s
         ON s.UserID=c.UserID
         AND s.PhoneNumber=c.PhoneNumber
      WHERE c.UserID=:id
      GROUP BY 1,2,3
      ORDER BY 2 DESC
   </sql-query>


and use the Transformations API instead:
Code:
         Session sess = getBroker().getSession();
         beginTransaction();
         List<CallHistoryRecord> list= sess.getNamedQuery("getCallHistory")
            .setResultTransformer(Transformers.aliasToBean(CallHistoryRecord.class))
            .setParameter("id", userId)
            .list();


This would be perfectly acceptable except that the CallHistoryRecord members include a couple of special types that I wish to map to (enums, a special telephone number class). I've sort of hacked this in the POJO itself. Are there any code samples of writing your own transformer to handle this properly?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.