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 do this more or less complex mapping?
PostPosted: Tue Dec 12, 2006 8:49 am 
Newbie

Joined: Tue Dec 12, 2006 5:01 am
Posts: 11
Hi,

I'm trying to set up a bit more complex mapping, but I don't get it to work.

I have Account and Company as tables which are related via a Person (both relationships simply 1:n). An Account has Funds (m:n, mapping table ACCOUNT_FUND). Now I want to give some statistics about Funds per Company. To avoid some complexity I introduced a view ACCOUNTS_BY_COMPANY.

What I want to do at the end is something like the following:

Code:
select ACCOUNT_FUND.FUND_ID,
       sum(ACCOUNT_FUND.AMOUNT) as AMOUNT
from ACCOUNT_FUND
right outer join ACCOUNTS_BY_COMPANY
on ACCOUNT_FUND.ACCOUNT_ID = ACCOUNTS_BY_COMPANY.ACCOUNT_ID
group by ACCOUNT_FUND.FUND_ID


but dynamically filtered by Company, so it is a bit more complex:

Code:
select ACCOUNT_FUND.FUND_ID,
       sum(ACCOUNT_FUND.AMOUNT) as AMOUNT
from ACCOUNT_FUND
right outer join ACCOUNTS_BY_COMPANY
on ACCOUNT_FUND.ACCOUNT_ID = ACCOUNTS_BY_COMPANY.ACCOUNT_ID
where ACCOUNTS_BY_COMPANY.COMPANY_ID IN (:companyIds)
group by ACCOUNT_FUND.FUND_ID


(See the additional where clause.)

And this is the part I don't get to work.

1. Hibernate does not like views when validating the schema.
Sorry, couldn't resist. But this one is really annoying as you always only get exceptions on runtime.

2. Filter

Code:
<class name="FundStatisticsData">
  <subselect>select ACCOUNT_FUND.FUND_ID,
                   sum(ACCOUNT_FUND.AMOUNT) as AMOUNT
             from ACCOUNT_FUND
             right outer join ACCOUNTS_BY_COMPANY
             on ACCOUNT_FUND.ACCOUNT_ID = ACCOUNTS_BY_COMPANY.ACCOUNT_ID
             group by ACCOUNT_FUND.FUND_ID
  </subselect>
  <!-- some mapping here -->
  <filter name="fundsByCompany" condition="ACCOUNTS_BY_COMPANY.COMPANY_ID in (:companyId)"/>
</class>
<filter-def name="fundsByCompany">
  <filter-param name="companyId" type="integer"/>
</filter-def>


Even with :companyId being only one value instead of a collection (which I need at the end) I get an obvious error. The condition is not applied to the join, but to the resulting temporary table:

Code:
select fundstatis0_.fund_id as fund1_7_, fundstatis0_.amount as amount7_ from (
    select ACCOUNT_FUND.FUND_ID,
           sum(ACCOUNT_FUND.AMOUNT) as AMOUNT
    from ACCOUNT_FUND
    right outer join ACCOUNTS_BY_COMPANY
    on ACCOUNT_FUND.ACCOUNT_ID = ACCOUNTS_BY_COMPANY.ACCOUNT_ID
    group by ACCOUNT_FUND.FUND_ID ) fundstatis0_
where ACCOUNTS_BY_COMPANY.COMPANY_ID in (?)


But the resulting temporary table has no longer any ACCOUNTS_BY_COMPANY.COMPANY_ID and I don't want to put it in as I would need additional calculations (first per company, second sum all values of selected companies) which only add inaccuracies.

3. Custom SQL Queries

So I got the idea it could work with custom SQL queries, especially as the reference seems to have similar queries with parameterized selection:

Code:
<class name="FundStatisticsData">
  <!-- some mapping here -->
  <loader query-ref="fundStatisticsData"/>
  <sql-query name="fundStatisticsData" read-only="true">
    <return alias="data" class="FundStatisticsData"/>
      select ACCOUNT_FUND.FUND_ID,
             sum(ACCOUNT_FUND.AMOUNT) as AMOUNT
      from ACCOUNT_FUND
      right outer join ACCOUNTS_BY_COMPANY
      on ACCOUNT_FUND.ACCOUNT_ID = ACCOUNTS_BY_COMPANY.ACCOUNT_ID
      where ACCOUNTS_BY_COMPANY.COMPANY_ID IN (:companyId)
      group by ACCOUNT_FUND.FUND_ID
  </sql-query>
</class>


This one works with executing the named query directly and applying the parameter. But that's not what I want. I neither get a FundStatisticsData object nor does it even apply my custom types, so I could execute pure SQL as well. And the recommended <return-property> does not have any support for types (where I don't understand why it should by different than <property> inside <class>). So what does Hibernate buy me here?

But it also DOES NOT WORK with a pure query on the mapped class FundStatisticsData:

Code:
session.createQuery("from FundStatisticsData")

fails with searching a table FundStatisticsData instead of using the specified SQL query via <loader query-ref=""/>. Additionally setting the param :companyId lets it fail in searching the parameter ("Could not locate named parameter [companyId].").

Now I really don't know how to go on or what to try else. This mapping does not look THAT complex.

Thanks in advance,
Jörg


Top
 Profile  
 
 Post subject: SQL query mapping
PostPosted: Tue Dec 12, 2006 2:11 pm 
Beginner
Beginner

Joined: Thu Apr 27, 2006 12:19 pm
Posts: 33
Location: Seattle, WA
Using a named SQL query instead of a view is usually what I do, largely because I don’t have the ability to run DDL SQL on our database servers, and also because the schema is complete garbage.

Your fundStatisticsData SQL query should be returning one result if you want to use the loader mapping element. As your mapping stands now Hibernate will use the fundStatisticsData query when loading by id:

session.load(FundStatisticsData.class, companyId);

If you want to return multiple instances of FundStatisticsData, as I suspect, then you’ll need to use a named SQL query.

Query qry = session.getNamedQuery(“fundStatisticsData”);
qry.setParameter(“companyId”, companyId);
List results = qry.list();

Trying to run an HQL query (from FundStatisticsData) against a class that is not mapped to a table, i.e. mapped via a custom SQL query will not work. Unfortunately using custom SQL to load entities takes away a lot of the power Hibernate would normally provide.


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.