一个真实的生产场景。背景:6个表格:基金,账户,期间,期货权重,持仓,头寸。休眠,如何在真实世界中加载复杂对象
Fund: The fund information, for example: fund name, total Asset, start time.. etc.
Account: each fund has an account (one to one) to fund.
period: time period (for example: 2000-01-01 to 2000-12-31)
periodweight: at a certain period, the target holding weight.
holding: IBM, Oracle, GE are stock holdings.
position: IBM($3000), oracle($2000), GE($5000)
如果我有一个基金名称:假基金,其中有一个目标保持为IBM(30%)中,Oracle(20%),GE(50%)的期间(2000-01-01至2000-12-31),2000-01-01的实际状况为10%,10%,80%,2000-01-02为20%,20%,60%表
Account: id account_Number Fund_id
* 1 0001 10
2 0002 11
Fund: id name other properties...
* 10 fake fund xxx
11 another fake one xxx
period: id start_time end_time fund_id
* 3 2000-01-01 2000-12-31 10
4 2001-01-01 2001-12-31 10
periodWeight: id target_weight holding_id period_id
*11 30% 21 3
*12 20% 22 3
*13 50% 23 3
holding: id name order other properties...
*21 IBM 1 xxx
*22 Oracle 2 xxx
*23 GE 3 xxx
position: id Account_id holding_id date actual_position
1 1 11 2000-01-01 10%
2 1 12 2000-01-01 10%
3 1 13 2000-01-01 80%
4 1 11 2000-01-02 20%
5 1 12 2000-01-02 20%
6 1 13 2000-01-02 60%
的Java类是
Account{
@onetoOne(mappedby="account")
Fund f;
@oneToMany
Set<Position> positions;
}
Fund{
@manyToOne
Account account;
@oneToMany(mappedby="fund")
Set<Period> periods;
}
Period{
@manyToOne
Fund fund;
@oneToMany(mappedby="period")
Set<PeriodWeight> periodWeights;
}
PeriodWeight{
@manyToOne
Period period;
@ManyToOne
Holding holding
}
Holding{
@OneToMany(mappedby="holding")
Set<PeriodWeight> periodWeights;
@OneToMany
Set<Position> positions;
}
Position{
@manyToOne
Account account;
@manyToOne
Holding holding;
}
我想有一个查询: 基地d日期(2000-01-01)和基金名称(假基金)。我想创建一个Fund对象,其中包含账户和期间(2000-01-01到2000-12-31),期间包含periodWeight,periodWeight包含持有,并且持有包含期权(2000-01-01 )。当没有这样的位置时,例如,我查询2000-01-03和假基金,我想要有结构,只是位置是持有的空集。
如果有数据,hql可以正确加载结构。
select f from Fund f
inner join fetch f.account a
inner join fetch f.period p
inner join fetch p.periodWeight w
inner join fetch w.holding h
inner join fetch h.positions po
where f.name=:name and :date between p.start_date and p.end_date and :date=po.date and po.account= a
问题是当位置表没有数据时,它返回null。当没有数据时,我需要一个sql来给我这个结构,它可以加载除了位置之外的所有东西,只需将位置设置为空即可。
另一个问题是加载这种复杂结构的更好方法是什么?一个像这样的hql,或者通过一个hql加载部分结构,然后通过另一个hql加载其他部分?因为在sql中,你总是一个接一个地加载它们,首先是基金,然后是期限,然后是权重,然后是持有,然后是持仓等。权重需要根据持有订单进行排序。
select f from Fund f
inner join fetch f.account a
inner join fetch f.period p
inner join fetch p.periodWeight w
inner join fetch w.holding h
left join fetch h.positions po with po.account= a and :date=po.date
where f.name=:name and :date between p.start_date and p.end_date
东西很接近,但是这给我的错误,
org.hibernate.hql.ast.QuerySyntaxException: with-clause not allowed on fetched associations; use filters
“问题是什么时候没有数据,它会返回null” - 没有数据在哪里?在职位协会? –
是的,当日期的位置表上没有数据时,我只有2000-01-01和2000-01-02的数据。当我查询2000-01-03和“假基金”时,它返回资金清单。 – Nan
我想我的第一个问题是,如果我想加载这样一个对象,我应该把它分成几个小步骤,而不是一次性加载所有内容?如果我使用太多迷你步骤,我就无法感受到休眠的好处。 – Nan