hibernate, Как загрузить сложный объект в реальном мире - PullRequest
6 голосов
/ 31 августа 2011

реальный сценарий производства.Справочная информация: 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;
}

. Я хочу получить запрос: на основена дату (2000-01-01) и название фонда (поддельный фонд).Я хочу создать объект Fund, который содержит учетную запись и период (с 2000-01-01 по 2000-12-31), а period содержит periodWeight, а periodWeight содержит удержание, а holding содержит позиции для (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

проблема в том, что когда в таблице позиций нет данных за этот день, возвращается ноль.Мне нужен 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

Ответы [ 2 ]

2 голосов
/ 09 июля 2013

Это досадное ограничение в HQL, с которым я несколько раз сталкивался в зависимости от времени.

Я обнаружил, что это решение HQL-запроса, содержащего предложения fetch и with:

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
where f.name=:name and :date between p.start_date and p.end_date
and (po is null or (po.account= a and :date=po.date))

Хитрость заключается в перемещении предложения with в where Предложение и добавить параметр для объекта, чтобы быть нулевым, что позволяет ему возвращать строки без позиции.

0 голосов
/ 31 августа 2011

Вы должны быть в состоянии сделать это, изменив:

inner join fetch h.positions p

на:

left join fetch h.positions p

и вызвав

query.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

на объекте запроса перед вамивыполнить запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...