Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Spring+Hibernate вопрос о работе с сессиями в DAO объектах / 23 сообщений из 23, страница 1 из 1
24.02.2013, 00:16:52
    #38163455
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Это какая-то базовая проблема настройки хибернейта, я в этом не силен. Друзья, поделитесь пожалуйста опытом, даже если это нубский вопрос

Конфигурация Spring:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
<bean id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
        p:driverClass="${jdbc.driverClassName}"
        p:jdbcUrl="${jdbc.databaseurl}"
        p:user="${jdbc.username}"
        p:password="${jdbc.password}" />

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
    	<list>
           <value>com.checkout.core.model</value>
       </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>            
            <prop key="hibernate.c3p0.min_size">10</prop>
			<prop key="hibernate.c3p0.max_size">200</prop>
			<prop key="hibernate.c3p0.timeout">90</prop>
			<prop key="hibernate.c3p0.max_statements">50</prop>
			<prop key="hibernate.c3p0.idle_test_period">3000</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>	

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
	<property name="sessionFactory" ref="sessionFactory" />
	<property name="maxResults" value="5000" />
</bean>

<bean id="abstractDAO" abstract="true" p:hibernateTemplate-ref="hibernateTemplate" class="com.checkout.core.dao.impl.AbstractDAOImpl" />



Реализация AbstractDAOImpl
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
@Repository
public abstract class AbstractDAOImpl<T extends DataObject> extends HibernateDaoSupport implements AbstractDAO<T> {

	protected Criteria createCriteria() {
		return getSession().createCriteria(getObjectClass());
	}

	protected Criteria createCriteria(String alias) {
		return getSession().createCriteria(getObjectClass(), alias);
	}	

	public List<T> list(int fromIndex, int toIndex, String orderBy, boolean isAscending, Filter filter, Map<String, Object> context) {
		Criteria criteria = createCriteria();
		List<T> result = criteria.list();
		// DetachedCriteria criteria = DetachedCriteria.forClass(getObjectClass());
		// List<T> result = getHibernateTemplate().findByCriteria(criteria, fromIndex, toIndex - fromIndex);
		// criteria.setProjection(Projections.rowCount());
		// context.put(PersistenceService.TOTAL_COUNT, getHibernateTemplate().findByCriteria(criteria, 0, 1).iterator().next());
		return result;
	}

	public T get(Long id) {
		return (T) getSession().get(getObjectClass(), id);
		// return getHibernateTemplate().get(getObjectClass(), id);
	}
	.....................................
}



Проблема вот в чем - в реализации AbstractDAOImpl. Там должен по-хорошему должен использоваться hibernateTemplate, который оперирует DetachedCriteria. Если объект, например User выбрать например с помощью

Код: java
1.
2.
3.
DetachedCriteria criteria = DetachedCriteria.forClass(getObjectClass());
criteria.addRestriction(Restrictions.eq("id", 1));
User user = getHibernateTemplate().findByCriteria(criteria).iterator().next();



то потом у User'а проблемы с ленивой инициализацией коллекции getRoles() - если просто взять user.getRoles(), то получим Lazy initialization exception, также эксепшн выдает и Hibernate.initialize(user.getRoles());

Поэтому я сделал так, как сейчас в коде

Код: java
1.
2.
3.
Criteria criteria = getSession().createCriteria(getObjectClass());
criteria.addRestriction(Restrictions.eq("id", 1));
User user = criteria.list().iterator().next();


при этом сессия сохраняется и если взять user.getRoles(), то все пройдет без проблем - коллекция проинициализируется сама. Проблема в том, что эти коннекшны совсем не убиваются, а подвисают и после нескольких обновлений страницы браузера все виснет на выполнении criteria.list() - наверное коннекшны закончились. Для обработки коннекшнов я подключил к хибернейту c3p0 кэш

Да и вообще проблема не в способе создании Criteria, а в способе взятия сессий - в методе public T get(Long id) такая же проблема будет

Спасибо
...
Рейтинг: 0 / 0
24.02.2013, 00:32:33
    #38163465
Лагман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Суть hibernate в том, чтобы предоставить объектную структуру во время выполнения транзакции. Для выноса объектов за пределы сервиса лучше копировать их в отдельные DTO.

P.S. вышеизложенное - моё личное имхо
...
Рейтинг: 0 / 0
24.02.2013, 01:28:55
    #38163491
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
По-моему в последних версиях идет отказ от hibernate template, в пользу второго варианта. У вас выходит в hibernate template создаётся своя сессия. Вот за пределами template её уже и не видно.
Если вы уверены что дело в соединениях, то нужно натравить транзакции на конкретные классы и методы. Почитайте про аннотацию @Transactional и поставьте её. В пределах метода обозначеного этой аннотацией можно будет загружать ленивые зависимости. А при выходе из такого метода контейнер закроет транзакцию и сессию.
Обратите внимате, что ленивые ассоциации можно загружать сразу же, если они нужны в конкретном методе с помощью FetchMode.
...
Рейтинг: 0 / 0
24.02.2013, 11:39:56
    #38163593
ТимоН
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
ЛагманСуть hibernate в том, чтобы предоставить объектную структуру во время выполнения транзакции. Для выноса объектов за пределы сервиса лучше копировать их в отдельные DTO.

P.S. вышеизложенное - моё личное имхо

Не боитесь что придется копировать 1 к 1? Как быть в случаях когда почти все объекты нужны за приделами сервиса?
...
Рейтинг: 0 / 0
24.02.2013, 14:04:30
    #38163675
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
BlazkowiczЕсли вы уверены что дело в соединениях, то нужно натравить транзакции на конкретные классы и методы. Почитайте про аннотацию @Transactional и поставьте её. В пределах метода обозначеного этой аннотацией можно будет загружать ленивые зависимости. А при выходе из такого метода контейнер закроет транзакцию и сессию.


Спасибо за советы. Но мне сделать метод @Transactional не подойдет - коллекциями ведь мне нужно пользоваться извне DAO, причем неизвестно какая пользователю понадобится, и если их загрузить сразу, тогда какой смысл в Lazy инициализации
...
Рейтинг: 0 / 0
24.02.2013, 17:51:02
    #38163807
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaНо мне сделать метод @Transactional не подойдет - коллекциями ведь мне нужно пользоваться извне DAO
@Transactional можно (и нужно) пользовать и вне DAO.

snawa, причем неизвестно какая пользователю понадобится, и если их загрузить сразу, тогда какой смысл в Lazy инициализации
Сценариев много. В одних нужны зависимости, в других нет. Lazy везде по-умолчанию, чтобы максимально обрезать ассоциации, где они, возможно, не нужны.
В любом случае чтобы догрузить ленивую ассоциацию, нужно держать открытую сессию. Которая вбольшинстве фреймверков 1-к-1 связана с транзакцией.
...
Рейтинг: 0 / 0
24.02.2013, 17:51:55
    #38163808
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Можно, конечно максимально расширить область видимости сессии с помощью OpenSessionInView, но это скорее заплатка, чем полноценное качественное решение.
...
Рейтинг: 0 / 0
24.02.2013, 20:34:20
    #38163892
Лагман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
ТимоН,

вариантов то нет, или отключать lazy или копировать, в чем тогда профит hibernate?
...
Рейтинг: 0 / 0
24.02.2013, 22:29:30
    #38163945
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaпричем неизвестно какая пользователю понадобится,
тут надо расшифровать, почему - неизвестно? В ГУИ неизвестно?
...
Рейтинг: 0 / 0
25.02.2013, 12:13:21
    #38164446
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Petro123snawaпричем неизвестно какая пользователю понадобится,
тут надо расшифровать, почему - неизвестно? В ГУИ неизвестно?
Да, из ГУИ могут использоваться разные коллекциия - смысла их всех инициализить нету
...
Рейтинг: 0 / 0
25.02.2013, 12:14:33
    #38164447
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaДа, из ГУИ могут использоваться разные коллекциия - смысла их всех инициализить нету
Жирный удаленный GUI? Правильно. Все инициализировать не нужно. А вот те которые нужны в каждом конкретном use-case - очень желательно.
...
Рейтинг: 0 / 0
25.02.2013, 12:15:31
    #38164449
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaPetro123пропущено...
тут надо расшифровать, почему - неизвестно? В ГУИ неизвестно?
Да, из ГУИ могут использоваться разные коллекциия - смысла их всех инициализить нету
верно. Нажали на сисок Городов по всей России - они загрузились.

Значит, когда нужно грузить - вызовется НУЖНЫЙ контроллёр. Так?
Т.е. мы в ГУИ не знаем, но на сервере всегда знаем. Так?
...
Рейтинг: 0 / 0
25.02.2013, 12:16:15
    #38164451
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
BlazkowiczsnawaНо мне сделать метод @Transactional не подойдет - коллекциями ведь мне нужно пользоваться извне DAO
@Transactional можно (и нужно) пользовать и вне DAO.

snawa, причем неизвестно какая пользователю понадобится, и если их загрузить сразу, тогда какой смысл в Lazy инициализации
Сценариев много. В одних нужны зависимости, в других нет. Lazy везде по-умолчанию, чтобы максимально обрезать ассоциации, где они, возможно, не нужны.
В любом случае чтобы догрузить ленивую ассоциацию, нужно держать открытую сессию. Которая вбольшинстве фреймверков 1-к-1 связана с транзакцией.

Т.е. @Transactional можно помечать методы в UI классах, где например сначала вычитывается объект, а потом берется его коллекция? Как-то это не очень с первого взгляда. Или это нормальная практика?
...
Рейтинг: 0 / 0
25.02.2013, 12:22:52
    #38164460
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaТ.е. @Transactional можно помечать методы в UI классах, где например сначала вычитывается объект, а потом берется его коллекция? Как-то это не очень с первого взгляда. Или это нормальная практика?
Достаточно трудно угадать что именно у вас за архитектура. Вы даже не сообщили у вас 3-tier или 2-tier.
Обычно дела обстоят так
UI, грубо говоря, запрашиваен данные у Domain Model, а вот Domain Model уже запускает транзакцию, вычитывает все необходимые данные и возвращает их. Дозагрузка данных в UI называется OpenSessionInView и, иногда, практикуется в Web. Хотя у этого подхода есть свои недостатки. В жирном gui такой подход сложно применить. В 3-tier, так вообще не возможно.
...
Рейтинг: 0 / 0
25.02.2013, 12:27:55
    #38164470
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
я бы делил вдругой плоскости.
Есть 10 контролов в ГУИ.
2 варианта:
- без AJAX все 10 грузятся заранее - никакойленивой загрузки. Либо она есть, но при запросе формы контроллёр грузит всё.
- с AJAX 3 контрула подгружаются по клику. Событе отправится в контроллёр и тоже знаем.

Какое вариант - решает БЛ а не программист.
...
Рейтинг: 0 / 0
25.02.2013, 18:34:32
    #38165323
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
BlazkowiczsnawaТ.е. @Transactional можно помечать методы в UI классах, где например сначала вычитывается объект, а потом берется его коллекция? Как-то это не очень с первого взгляда. Или это нормальная практика?
Достаточно трудно угадать что именно у вас за архитектура. Вы даже не сообщили у вас 3-tier или 2-tier.
Обычно дела обстоят так
UI, грубо говоря, запрашиваен данные у Domain Model, а вот Domain Model уже запускает транзакцию, вычитывает все необходимые данные и возвращает их. Дозагрузка данных в UI называется OpenSessionInView и, иногда, практикуется в Web. Хотя у этого подхода есть свои недостатки. В жирном gui такой подход сложно применить. В 3-tier, так вообще не возможно.

3-tier, веб-приложение с использованием ZK framework
Поясню немного схему - допустим на UI есть два метода контроллера,
Код: java
1.
2.
3.
4.
5.
ViewController{
    public void fillUserList()
    
    public void fillUserTable()
}



один получает из сервиса список пользователей, чтобы отобразить их фамилии, а другой получает список пользователей, чтобы отобразить их в таблице с колонками "фамилия", "список ролей", список ролей берется из lazy коллекции user.getRoles(). При этом дергается один и тот же метод сервиса UserService.getUsers(), который в свою очередь обращается к UserDAO, примерную реализацию которого я описал выше. Причем во ViewController я не хочу беспокоится о том, загружены данные или нет - просто выполняю user.getRoles() в любом месте.
...
Рейтинг: 0 / 0
25.02.2013, 18:45:23
    #38165336
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawa3-tier, веб-приложение с использованием ZK framework
Причем во ViewController я не хочу беспокоится о том, загружены данные или нет.
Собственно весь вопрос в эти два предложения можно было уложить.
Ой! Что-тут у нас? Не к столу будет сказано OpenSessionInView от ZK:
http://www.zkoss.org/javadoc/latest/zk/org/zkoss/zkplus/hibernate/OpenSessionInViewListener.html

Ну, и для самообразования рекомендую
http://blog.frankel.ch/the-opensessioninview-antipattern
...
Рейтинг: 0 / 0
25.02.2013, 18:56:08
    #38165357
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaво ViewController я не хочу беспокоится о том, загружены данные или нет
только что мы не знали, где у нас какие свойство нужны. Теперь [внезапно] все мы прекрасно знаем: в fillUserList() нам нужны только имена, в fillUserTable нам нужны роли. Спрашивается, почему бы не фетчить что надо, там где это надо.
...
Рейтинг: 0 / 0
25.02.2013, 20:21:02
    #38165482
snawa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Blazkowiczsnawa3-tier, веб-приложение с использованием ZK framework
Причем во ViewController я не хочу беспокоится о том, загружены данные или нет.
Собственно весь вопрос в эти два предложения можно было уложить.
Ой! Что-тут у нас? Не к столу будет сказано OpenSessionInView от ZK:
http://www.zkoss.org/javadoc/latest/zk/org/zkoss/zkplus/hibernate/OpenSessionInViewListener.html

Ну, и для самообразования рекомендую
http://blog.frankel.ch/the-opensessioninview-antipattern

про OpenSessionInView слышал, но в основном негатив. Типа используйте, но лучше не надо. Неужели нету никакой хорошей практики?

chpashasnawaво ViewController я не хочу беспокоится о том, загружены данные или нет
только что мы не знали, где у нас какие свойство нужны. Теперь [внезапно] все мы прекрасно знаем: в fillUserList() нам нужны только имена, в fillUserTable нам нужны роли. Спрашивается, почему бы не фетчить что надо, там где это надо.

По вашему, в сервисе по работе с юзером, у которого например две lazy коллекции нужно заранее предусмотреть методы
getUsersWithoutInit(), getUsersWithRoles(), getUsersWithOtherCollection(), getUsersWithRolesAndOtherCollection() и т.д. до n! ? Бред кажется
...
Рейтинг: 0 / 0
25.02.2013, 20:39:28
    #38165507
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaПо вашему, в сервисе по работе с юзером, у которого например две lazy коллекции нужно заранее предусмотреть методы
getUsersWithoutInit(), getUsersWithRoles(), getUsersWithOtherCollection(), getUsersWithRolesAndOtherCollection() и т.д. до n! ? Бред кажетсяэто разумный компромисс между "тащить все" и "загружать все лениво" потому что ни один из этих подходов не является оптимальным с точки зрения производительности. а с точки зрения удобства программера оба подхода конечно зашибись, в любом случае ничего не надо делать.

по поводу кучи методов - если повторяющиеся запросы достаточно сложны, выделите общую часть с помощью criteria, и в каждом методе добавляй только изменяющийся фетч.
...
Рейтинг: 0 / 0
25.02.2013, 21:16:30
    #38165544
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawa,
Давай хоть один негатив про сессию на окно-форму.
Правильно сказали - нет золотой пули.
...
Рейтинг: 0 / 0
25.02.2013, 21:16:42
    #38165545
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
snawaПо вашему, в сервисе по работе с юзером, у которого например две lazy коллекции нужно заранее предусмотреть методы getUsersWithoutInit(), getUsersWithRoles(), getUsersWithOtherCollection(), getUsersWithRolesAndOtherCollection() и т.д. до n! ? Бред кажется
В среднем, хватает 2х-3х вариантов: загрузить одного юзера, но со всеми зависимостями; загрузить список без зависимостей; загрузить список с какими-то конкретными зависимостями.
У вас в системе не будет 100500 вариантов показа списка пользователей.
Ну, и на крайний случай, если таки надо 100500 вариантов (что само по себе подозрительно), то всегда можно из сервиса, в DAO передать список свойств, для которых нужен Eager Fetch.
Код: java
1.
2.
3.
4.
5.
6.
7.
List<User> getUsers(String ... fetchProperties){
     ...
     for(String property : fetchProperties){
        criteria.setFetchMode(property, FetchMode.JOIN);
     }
     ...
}


Есть, правда, нюанс, что JOIN не всегда, подходит, иногда таки нужен Select, но это уже детали реализации классов User/UserDAO
...
Рейтинг: 0 / 0
25.02.2013, 21:24:09
    #38165552
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Spring+Hibernate вопрос о работе с сессиями в DAO объектах
Blazkowicz,
Да. Я думаю, вариантов будет не больше чем контролов в окне форме.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Spring+Hibernate вопрос о работе с сессиями в DAO объектах / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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