Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Controller Service DAO / 13 сообщений из 13, страница 1 из 1
28.09.2015, 17:31
    #39063408
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Здравствуйте!
Начал писать как говорится здесь
Для примера взял базу из трех таблиц 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.
public class HomeController {

	@Autowired
	private IUserService userService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
			Long id = (long) 1;
		User user;
		Set<Authority> listAuthority;
		user = userService.getById(User.class, id);
		listAuthority = user.getListAuthority();
		System.out.println("User name: " + user.getLogin());

		Iterator<Authority> it = listAuthority.iterator();
		while (it.hasNext()) {
			Authority element = it.next();
			System.out.println("Authority role: " + element.getRole());
		}


Ну и конечно же получаю 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 загрузкой, и все эти объекты мне надо отдать контроллеру...
...
Рейтинг: 0 / 0
28.09.2015, 17:42
    #39063433
no56892
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Самое лучшее - сделать на REST поверх @Stateless (аналог есть в спринге, тогда транзакция вообще на весь запрос). Или в дао передавать список полей кот надо проинициализировать.
...
Рейтинг: 0 / 0
28.09.2015, 17:46
    #39063444
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Не читайте о программировании на хабре. Уровень ламмерства в этом вопросе там зашкаливает, за исключением пары авторов и переводов.
Сложно сразу ответить на весь сумбур, поэтому просто начнем с начала.
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 можно явно указать какие ленивые свойства нужно прогрузить сразу и как.
...
Рейтинг: 0 / 0
28.09.2015, 17:51
    #39063451
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
public class HomeController {

	@Autowired
	private IUserService userService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
			Long id = (long) 1;
		User user; //Зачем объявлять переменные заранее? Только захламляется код.
		Set<Authority> listAuthority;
		user = userService.getById(User.class, id); //Зачем User.class, если у нас же и так IUserService используется?
		listAuthority = user.getListAuthority();
		System.out.println("User name: " + user.getLogin());

		Iterator<Authority> it = listAuthority.iterator(); // Жесть какая, for чем не угодил??
		while (it.hasNext()) {
			Authority element = it.next();
			System.out.println("Authority role: " + element.getRole());
		}
...
Рейтинг: 0 / 0
28.09.2015, 18:14
    #39063480
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
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 можно явно указать какие ленивые свойства нужно прогрузить сразу и как
А можно какой-нибудь пример или ссылочку пжлст?
...
Рейтинг: 0 / 0
28.09.2015, 18:22
    #39063488
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Для 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. Это решаемо. Другое дело что бизнес-логики не должно быть в контроллере по этой причине, чтобы не дублировать её в каждом фасаде.
...
Рейтинг: 0 / 0
28.09.2015, 19:20
    #39063546
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Blazkowicz,

Идея неплохая.
А как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например...
как все такие связи подтянуть...
Не теряют ли смысл тогда связи oneTomany и ей подобные
...
Рейтинг: 0 / 0
29.09.2015, 09:25
    #39063792
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
doofyА как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например...
как все такие связи подтянуть...

Что-то типа
.setFetchMode("bList.cList.dList", FetchMode.EAGER)
?

doofyНе теряют ли смысл тогда связи oneTomany и ей подобные
Нет. В одном сценарии нужен только список имен A, и тогда зависимости тянуть не нужно.
В другом случае нужно загрузить A по ID со всеми зависимостями, и тогда выставляем FetchMode и грузим всё что нужно для конкретного сценария.

Причем, можно пробовать манипулировать JOIN/SELECT, чтобы оптимизировать производительность запроса.
...
Рейтинг: 0 / 0
29.09.2015, 10:44
    #39063905
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
BlazkowiczdoofyА как в таком случае быть: в A List<B>, в B List<C>, в C List<D> например...
как все такие связи подтянуть...

Что-то типа
.setFetchMode("bList.cList.dList", FetchMode.EAGER)
?

doofyНе теряют ли смысл тогда связи oneTomany и ей подобные
Нет. В одном сценарии нужен только список имен A, и тогда зависимости тянуть не нужно.
В другом случае нужно загрузить A по ID со всеми зависимостями, и тогда выставляем FetchMode и грузим всё что нужно для конкретного сценария.

Причем, можно пробовать манипулировать JOIN/SELECT, чтобы оптимизировать производительность запроса.

Блин не совсем я понял. Могли бы вы дать какой нибудь пример пжлст?
...
Рейтинг: 0 / 0
29.09.2015, 10:47
    #39063909
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
doofyБлин не совсем я понял. Могли бы вы дать какой нибудь пример пжлст?
Примеры из мануала чем не угодили?
18206253
...
Рейтинг: 0 / 0
29.09.2015, 10:47
    #39063911
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
doofy,

Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С.
И все они должны быть проинициализированы.
С вложенностью порядка 1 все понятно а как быть с большей не понимаю
...
Рейтинг: 0 / 0
29.09.2015, 11:01
    #39063932
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
doofydoofy,

Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С.
И все они должны быть проинициализированы.
С вложенностью порядка 1 все понятно а как быть с большей не понимаю

Ну, для кого я тут код привел?
18207982

Вот ещё пример
http://stackoverflow.com/a/13414768
...
Рейтинг: 0 / 0
29.09.2015, 13:45
    #39064162
doofy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Controller Service DAO
Blazkowiczdoofydoofy,

Ну т.е. Интересует момент когда есть "вложенность объектов". В A есть B, в B есть С.
И все они должны быть проинициализированы.
С вложенностью порядка 1 все понятно а как быть с большей не понимаю

Ну, для кого я тут код привел?
18207982

Вот ещё пример
http://stackoverflow.com/a/13414768
Да мы в одно время почти написали. Я писал ответ в этот момент. Посмотрю примеры внимательней, спс!
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Controller Service DAO / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]