|
|
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Здравствуйте! Начал писать как говорится здесь Для примера взял базу из трех таблиц User 1-* UserAuthorities *-1 Authority В Domain связал User и Authority связью many-to-many(fetch = FetchType.LAZY) Реализовал UserServiceImpl и в HomeController пишу значит: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Ну и конечно же получаю LazyInitializationException. Почитал про способы борьбы с исключением и что то нахлынула тоска... Потом наткнулся на статью , где пользователь BVadim пишет BVadimЯ столкнулся с данной проблемой во время разработки WEB-приложения. Разрабатывал на Spring + Hibernate. Решил проблему таким образом: Система делится на слои: Controller Service DAO Каждый метод в Service является логически завершённым. Они проектировались так, чтобы за его пределами к этой группе данных обращаться было уже не нужно. Методы Service обращаются к 1 или более методам DAO (За исключением тех которым не нужно обращаться в БД). С помощью аннотации @Transactional, которая предоставляется Spring`ом, каждый метод Service работает в одной транзакции и, соответственно, внутри него сессия открыта. Можно свободно получать доступ к lazy-полям. Controller получает уже готовые наборы данных для передачи их в представление. Таким образом получается работа без костылей и, одновременно, хорошо структурированный по логическим блокам код в Service-слое. Не спорю, так то можно конечно к ним доступ получить. Ну а я что бизнес логику получается выношу в контроллер тем, что там хочу обратиться к lazy объектам? Или так как я написал никто не делает. И все свои супер запросы к БД пихают в эти методы с аннотацией @Transactional. Для чего тогда городить service не пойму. Или как им пользоваться? ...не понимаю... А как поступить если у меня есть связанных скажем 4-5 таблиц с lazy загрузкой, и все эти объекты мне надо отдать контроллеру... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 17:31 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Самое лучшее - сделать на REST поверх @Stateless (аналог есть в спринге, тогда транзакция вообще на весь запрос). Или в дао передавать список полей кот надо проинициализировать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 17:42 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Не читайте о программировании на хабре. Уровень ламмерства в этом вопросе там зашкаливает, за исключением пары авторов и переводов. Сложно сразу ответить на весь сумбур, поэтому просто начнем с начала. Controller это часть MVC, в нём находится только подготовка данных к выводу и обработка пользовательского ввода. Service это Transaction Script - уже название "какбе" намекает. Этот слой реализует бизнес-логику приложения в виде бизнес-транзакций. DAO - устаревший паттерн, так как с ORM его польза совсем не очевидна. Правильный паттерн это Repository - просто хранилище, которое отдаёт объекты и персистит их. И не важно что там внутри. Теперь про Lazy. Использование @Transactional в контроллере с одной стороны и не так плохо. С другой стороны, это решение не полное. Шаблон может рендерится за пределами метода контроллера, что приведет к тому же LazyInitializationException. Полное решение называется Open Session in View, когда scope ORM сессии расширяется на всю обработку HTTP запроса. Кстати, транзакция и ORM сессия другу-другу немного перпендикулярны. Просто в большинстве случаев у них scope совпадает. Но это бывает не всегда. Наличие транзакции в контроллере никак не мешает держать бизнес-логику в Service. Наличие и отсутствие транзакции не должно влиять на то как распределен слой. Нужно управлять транзакцией над кодом, а не ломать код ради транзакции. Сам подход Open Session in View не самое лучшее решение, так как при необдуманном использовании быстро выливается в проблему N+1. Оптимальным вариантом, ИМХО, является явное указание нужных зависимостей. Через HQL и Criteria API можно явно указать какие ленивые свойства нужно прогрузить сразу и как. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 17:46 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 17:51 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Blazkowicz//Зачем User.class, если у нас же и так IUserService используется? Там у меня DAO и Service с Generic'ми. Прошу простить, что скрыл сей факт, но думаю он не очень важен. Blazkowicz// Жесть какая, for чем не угодил?? ахаха)) Это просто попробовал) BlazkowiczOpen Session in View Я пока не очень в теме,но слышал, что возникают проблемы, если "используется не HTTP". Вырвано из контекста но суть там была такая: "Кроме этого решение будет размазано, если, например web-service не HTTP". А как вы смотрите на способ Hibernate.initialize? Что из них более "эффективное" что ли.. для долгой жизни проекта? Вообще слышал про 1) Open Session in View 2) Hibernate.initialize 3) HQL BlazkowiczЧерез HQL и Criteria API можно явно указать какие ленивые свойства нужно прогрузить сразу и как А можно какой-нибудь пример или ссылочку пжлст? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 18:14 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Для Hibernate.initialize ещё и всё дерево объектов рефлексией обойти нужно. Не, ну можно, конечно. Мы так даже делали местами. Но проблемы N+1 это не решает. Вот это, по-моему скромному мнению, самый правильный способ. https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html#querycriteria-dynamicfetching Пассажа про не HTTP не понял. Open Session In View - навешивается любым интерцептором для любого фасада, MVC, Web Service, да хоть RMI и protobuf. Это решаемо. Другое дело что бизнес-логики не должно быть в контроллере по этой причине, чтобы не дублировать её в каждом фасаде. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 18:22 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Blazkowicz, Идея неплохая. А как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например... как все такие связи подтянуть... Не теряют ли смысл тогда связи oneTomany и ей подобные ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.09.2015, 19:20 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
doofyА как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например... как все такие связи подтянуть... Что-то типа .setFetchMode("bList.cList.dList", FetchMode.EAGER) ? doofyНе теряют ли смысл тогда связи oneTomany и ей подобные Нет. В одном сценарии нужен только список имен A, и тогда зависимости тянуть не нужно. В другом случае нужно загрузить A по ID со всеми зависимостями, и тогда выставляем FetchMode и грузим всё что нужно для конкретного сценария. Причем, можно пробовать манипулировать JOIN/SELECT, чтобы оптимизировать производительность запроса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 09:25 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
BlazkowiczdoofyА как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например... как все такие связи подтянуть... Что-то типа .setFetchMode("bList.cList.dList", FetchMode.EAGER) ? doofyНе теряют ли смысл тогда связи oneTomany и ей подобные Нет. В одном сценарии нужен только список имен A, и тогда зависимости тянуть не нужно. В другом случае нужно загрузить A по ID со всеми зависимостями, и тогда выставляем FetchMode и грузим всё что нужно для конкретного сценария. Причем, можно пробовать манипулировать JOIN/SELECT, чтобы оптимизировать производительность запроса. Блин не совсем я понял. Могли бы вы дать какой нибудь пример пжлст? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 10:44 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
doofyБлин не совсем я понял. Могли бы вы дать какой нибудь пример пжлст? Примеры из мануала чем не угодили? 18206253 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 10:47 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
doofy, Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С. И все они должны быть проинициализированы. С вложенностью порядка 1 все понятно а как быть с большей не понимаю ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 10:47 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
doofydoofy, Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С. И все они должны быть проинициализированы. С вложенностью порядка 1 все понятно а как быть с большей не понимаю Ну, для кого я тут код привел? 18207982 Вот ещё пример http://stackoverflow.com/a/13414768 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 11:01 |
|
||
|
Controller Service DAO
|
|||
|---|---|---|---|
|
#18+
Blazkowiczdoofydoofy, Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С. И все они должны быть проинициализированы. С вложенностью порядка 1 все понятно а как быть с большей не понимаю Ну, для кого я тут код привел? 18207982 Вот ещё пример http://stackoverflow.com/a/13414768 Да мы в одно время почти написали. Я писал ответ в этот момент. Посмотрю примеры внимательней, спс! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2015, 13:45 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39063444&tid=2124877]: |
0ms |
get settings: |
7ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
42ms |
get topic data: |
8ms |
get forum data: |
3ms |
get page messages: |
55ms |
get tp. blocked users: |
1ms |
| others: | 211ms |
| total: | 348ms |

| 0 / 0 |
