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