![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Ортхэннер |
|
||||||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Имеем следующий класс:
Можно ли одним запросом "выдернуть" всех потомков исходного объекта вне зависимости от поколения? (т. е. чтобы не только
но и
и т. д.) |
||||||
|
|||||||
Plamenk |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 258 Регистрация: 18.2.2003 Репутация: нет Всего: 3 |
Средствами Oracle можно. См. "connect by prior".
Но судя по коду ты работаешь с объектами не БД... так что этот способ здесь наверное не поможет. |
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Если ты вытянешь корневой объект (т.е. предка для тех потомков которые ищешь), то связанные объекты будут загружены либо автоматом (для односсылочных связей), либо лениво. Фактически делать ничего не нужно, только грамотно ссылки перебрать.
|
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Да знаю я, что они лениво будут загружены! Только дело-то в том как раз, что мне не надо, чтобы они грузились! Иначе приложение память будет кушать только в путь, да и медленнее обходить дерево таким образом, нежели на автомате. Ну ты сам посуди - это ж надо всё дерево будет в память загрузить. Куда это годится?
2 Plamenk: это и правда не оракул. Это Java Persistence. То есть БД там есть, но спрятана достаточно глубоко, и добраться до неё... можно, но, опять же, где гарантия, что это будет Oracle? у меня на машине вообще Java DB стоит... а надо, чтобы и с мусклом работало, и с Postgres... так что SQL-запросы если и можно использовать, то очень осторожно. |
|||
|
||||
tux |
|
||||
![]() Летатель ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1853 Регистрация: 10.2.2005 Где: msk.ru Репутация: 74 Всего: 132 |
Мне кажется или у вас что-то здесь не сходится? Если надо загрузить всех потомков, тогда будет кушать, если не надо, тогда не будет. По-моему, все просто. Не вижу проблем в обходе дерева, причем тут скорость не понятно. Плоский массив и дерево память будут расходовать одинаково - объекты одни и те же. Причем тут проблемы с памятью не ясно. Если нужно загрузить сразу все, просто поставь lazy=false. |
||||
|
|||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 10 Всего: 40 |
Уважаемые, если выйти из тени JPA, то вот статья для размышления Дерево каталогов Nested Sets
|
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
В JPA это будет как fetch=FetchType.EAGER в аннотации типа связи. |
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Сорри, неправильно выразился. Надо получить количество потомков объекта. Но всех, а не только непосредственных. А скорость здесь при том, что обход дерева - задача более трудоёмкая, нежели перебор массива. К тому же рекурсия сама по себе склонна потреблять больше памяти, чем итерационные алгоритмы, - за счёт стека. |
|||
|
||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 10 Всего: 40 |
||||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Уважаемый пугает своей наивностью. Всему своё место, знаете ли. Мне просто реально памяти не хватит - всё дерево обойти в нескольких потоках одновременно. StackOverflowError - видели такое?
|
|||
|
||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 10 Всего: 40 |
Какой же такой гигантской глубины у вас дерево, если стека не хватает?
|
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Да не в глубине дело, вернее, не только в ней... кстати она не фиксирована, в общем случае - от 4 и выше. Там на последних двух уровнях у каждого узла уйма потомков получается. :-\ А поскольку крутится всё это не само по себе, а в компании много чего ещё - доступный объём памяти оказывается весьма ограничен. Плюс каждый поток работает с базой самостоятельно (пул, конечно, есть, но от этого не легче - это ж пул соединений с БД, а когда данные уже извлечены...), то есть при подключении десяти клиентов в памяти окажется десять "деревьев". И тут реально одно из двух - или OutOfMemoryError, или StackOverflowError, смотря по тому, хватит памяти на загрузку последней копии базы или нет. В любом случае дёргать объекты получается некошерно. Можно, конечно, делать выборку чисто ID... в этом случае памяти хватит. Но, откровенно говоря, хотелось бы всё-таки переложить эту работу на сервер приложений, а не трахаться самому... вот и интересуюсь - есть способ?
|
|||
|
||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 10 Всего: 40 |
ну-ну, от такой рекурсии просто почти стопроцентное попадание на переполнение стека. Добавлено через 7 минут и 50 секунд всё, больше в занозу не лезу. ![]() |
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Платон, хочешь верь, хочешь нет, но такая ситуация реально была. Ты знаешь, сколько объектов находится на одном уровне иерархии? или размер в памяти одного объекта? или объём доступной памяти? нет?
Тогда хватит иронизировать. Нечего посоветовать по сабжу, лучше и правда молчи. |
|||
|
||||
Hroft |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 20.10.2003 Где: Москва Репутация: нет Всего: 3 |
Мне кажется, Platon всего лишь хотел сказать, что у вас принципиально что-то неправильно продумано. Он хочет вам помочь, а не выслушивать "да я сам все знаю, все умею, и вы ни фига не представляете, что у меня тут за МЕГАЗАДАЧА". Нужно как-то уважительнее относиться друг к другу.
Да, ситуации бывают разные. Но за 7 лет программирования я не видел ни одного StackOverflowError, вызванного сложностью задачи. Зато видел предостаточно вызванных... ммм... некорректным кодом. Даже если рекурсия глубокая, кто заставляет хранить данные в автопеременных? Для больших объемов данных есть куча, может быть, полезно будет свой менеджер памяти небольшой сваять, хотя, опять же, в яве все это смотрится более чем подозрительно. |
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 28 Всего: 159 |
Я так понимаю что задача сводится к нахождению всех листовых узлов дерева объектов. А может попробовать грамотно запрос на JPA написать, который их находить будет?
|
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Hroft:
В Java менеджер памяти заменить, к сожалению, впрямую нельзя (ограничения безопасности). Есть объекты-ссылки, позволяющие в какой-то степени разрулить ситуацию, когда памяти не хватает, но если полагаться на fetch=FetchType.EAGER в JPA, то пристроить эти объекты оказывается уже некуда. Может быть (и даже более вероятно), не StackOverflow, а OutOfMemory, но... с точки зрения результата - невелика разница. :( Мне памяти-то доступно метров, может, двадцать. А когда на листьях оказываются объекты размерчиком эдак по килобайту, и их несколько тысяч... а теперь представьте, что эту же структуру из базы дёргают ещё два-три хотя бы потока (а их будет не два-три)... и всё, "приплыли", как говорится. Веб-приложение, чтоб его. :-\ powerOn, типа того, но не совсем. Мне бы количество узлов в конкретной ветви дерева найти. Листья-то что - запрос вроде вот этого, и всё:
Можно, конечно, извратиться и использовать вложенный запрос, но зачем? - и так сработает. А вот как посчитать количество вообще всех потомков конкретного узла - это вопрос... |
|||
|
||||
Hroft |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 310 Регистрация: 20.10.2003 Где: Москва Репутация: нет Всего: 3 |
Не знаю, насколько здравым будет предложение, но вот оно.
А что, если при помощи вообще сторонней программки просто создать сущность, хранящую необходимую информацию? Тупо написать обычную программу, которая с какой-то периодичностью будет обновлять эти данные. В результате при работе ограниченной по памяти (и времени, насколько я понимаю) программы вообще не будет ничего ни загружаться, ни считаться. На память сторонней программы, которая уж точно будет работать в один поток и иметь больше 20 мегов памяти в своем распоряжении, нам, по сути, наплевать. Пойдет так? Это сообщение отредактировал(а) Hroft - 23.9.2008, 10:58 |
|||
|
||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 10 Всего: 40 |
По мне так очень здравое, и вообще можно сделать в логику программы инкремент в этой таблице. Получится запросов всего 4+, и памяти минимум. |
|||
|
||||
Ортхэннер |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 29.1.2005 Где: Благовещенск Репутация: нет Всего: нет |
Действительно, мысль интересная. В принципе, попробовать ничто не мешает, хотя при этом в промежутке между обновлениями индекса пользователь будет получать недостоверную информацию (кстати, проверено - часто такую прогу не позапускаешь, во время анализа загрузка процессора растёт очень сильно, а снижать приоритет потоку - так он работать будет дольше желаемого). Ещё можно всё-таки сделать рекурсию в самой программе, но дёргать только ID объектов базы, а не сами объекты. Возни чуть больше, но зато в память укладываюсь, особенно если обернуть их в PhantomReference. Плюс - ID выбирается шустрее, чем сам объект, что тоже очень приятно. А количество прямых потомков узла при этом определяется автоматически - по длине результирующего списка. Не так уж сложно. "Дёрнуть" из базы после этого связанную сущность по какому-либо критерию тоже не проблема, QL-запросам можно же коллекции в качестве параметров передавать?
|
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |