Hibernate не обновляет запись - Wicket - PullRequest
9 голосов
/ 23 июля 2010

Я работаю над веб-приложением с Wicket, Spring и Hibernate, и у меня возникла проблема с обновлением записей.Я проверил, что метод saveOrUpdate вызывается, и что данные в объекте домена изменились.Вывод SQL, однако, не показывает, что в базу данных были внесены какие-либо изменения (например, UPDATE), а соответствующая запись не была обновлена.

Я думаю, что имеет больше смысла использовать update (), ноЯ saveOrUpdate () удается создать новые записи, но не обновляет их.Я проверил, что этот метод вызывается, и переданный UserVO содержит обновленные поля.Вот метод DAO: public class SkuldwebDAOImpl extends HibernateDaoSupport implements SkuldwebDAO { public void updateUser(UserVO userVO) { getSession().saveOrUpdate(userVO); } }

Вот мой файл свойств: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/skuldweb_dev;AUTO=MULTI;CURSOR=READONLY jdbc.username= jdbc.password= hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.use_outer_join=true<br> hibernate.cache.use_query_cache=true hibernate.cache.use_second_level_cache=true hibernate.cache.provider=org.hibernate.cache.HashtableCacheProvider<br> hibernate.schemaUpdate=true

Вот бин sessionFactory в applicationContext.xml: <pre> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="use_outer_join">${hibernate.use_outer_join}</prop> <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop> <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop> <prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop> <prop key="hibernate.connection.pool_size">10</prop> <prop key="hibernate.connection.autocommit">true</prop> <prop key="hibernate.jdbc.batch_size">1000</prop> <prop key="hibernate.bytecode.use_reflection_optimizer">true</prop> </props> </property> <property name="annotatedClasses"> <list> <value>com.upbeat.app.skuldweb.domain.UserVO</value> <value>com.upbeat.app.skuldweb.domain.UserLevelVO</value><br> </list> </property> <property name="schemaUpdate" value="${hibernate.schemaUpdate}"/> </bean>

Надеемсяодин из вас может мне помочь.

Обновлено Вот некоторая информация из журнала (onSubmit () выделяет эти записи в журнале - последняя запись должна быть, когда запрос обрабатываетсяперенаправлен на другую страницу (после обновления записи).


[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:239): Using SessionFactory 'sessionFactory' for OpenSessionInViewFilter
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:214): Returning cached instance of singleton bean 'sessionFactory'
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:181): Opening single Hibernate Session in OpenSessionInViewFilter
[DEBUG] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:318): Opening Hibernate Session
[DEBUG] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.(SessionImpl.java:247): opened session at timestamp: 5242215490777088
[TRACE] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1316): setting flush mode to: NEVER
[DEBUG] 2010-07-23 00:29:26,305 :org.apache.wicket.Session.getPage(Session.java:700): Getting page [path = 4:userprofile_form, versionNumber = 0]
[DEBUG] 2010-07-23 00:29:26,306 :org.apache.wicket.markup.html.form.persistence.CookieValuePersister.getCookie(CookieValuePersister.java:210): Unable to find Cookie with name=userprofile_form.email and request URI=/upbeat-app-skuld-web/
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.engine.IdentifierValue.isUnsaved(IdentifierValue.java:127): id unsaved-value: 0
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:546): detached instance of: com.upbeat.app.skuldweb.domain.UserVO
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228): updating detached instance
[TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295): updating [com.upbeat.app.skuldweb.domain.UserVO#1]
[TRACE] 2010-07-23 00:29:26,310 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346): updating [com.upbeat.app.skuldweb.domain.UserVO#1]
[TRACE] 2010-07-23 00:29:26,311 :org.hibernate.engine.Cascade.cascade(Cascade.java:138): processing cascade ACTION_SAVE_UPDATE for: com.upbeat.app.skuldweb.domain.UserVO
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:239): cascading to saveOrUpdate: com.upbeat.app.skuldweb.domain.UserLevelVO
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.engine.IdentifierValue.isUnsaved(IdentifierValue.java:127): id unsaved-value: 0
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:546): detached instance of: com.upbeat.app.skuldweb.domain.UserLevelVO
[TRACE] 2010-07-23 00:29:26,312 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228): updating detached instance
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295): updating [com.upbeat.app.skuldweb.domain.UserLevelVO#1]
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346): updating [com.upbeat.app.skuldweb.domain.UserLevelVO#1]
[TRACE] 2010-07-23 00:29:26,313 :org.hibernate.engine.Cascade.cascade(Cascade.java:173): done processing cascade ACTION_SAVE_UPDATE for: com.upbeat.app.skuldweb.domain.UserVO
[DEBUG] 2010-07-23 00:29:26,314 :org.apache.wicket.RequestCycle.setRequestTarget(RequestCycle.java:644): replacing request target org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget@676067951[Page class = com.upbeat.app.skuldweb.web.user.UserProfilePage, id = 4, version = 0]->userprofile_form->interface org.apache.wicket.markup.html.form.IFormSubmitListener.IFormSubmitListener (request paramaters: [RequestParameters  componentPath=4:userprofile_form pageMapName=null versionNumber=0 interfaceName=IFormSubmitListener componentId=null behaviorId=null urlDepth=-1 parameters={email=john@upbeat.no,userprofile__form2_hf_0=} onlyProcessIfPathActive=false]) with [BookmarkablePageRequestTarget@1030849724 pageClass=com.upbeat.app.skuldweb.web.user.UserProfilePage]

Обновление 2 Вот UserVO без методов получения / установки <pre> @Entity @Table(name = "USERS") @NamedQueries({ @NamedQuery(name = "user.getById", query = "from UserVO item where item.id = :id"), @NamedQuery(name = "user.getAllUsers", query = "from UserVO item order by item.registerDate desc"), @NamedQuery(name = "user.countAll", query = "select count(item) from UserVO item"), @NamedQuery(name = "user.getByUsername", query = "from UserVO item where item.username = :username"), @NamedQuery(name = "user.authenticate", query = "from UserVO item where item.username = :username AND item.passwordHash = :passwordHash") }) public class UserVO extends BaseVO {</p> <pre><code>@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") protected long id; @OneToOne(cascade = CascadeType.ALL) protected UserLevelVO userLevelVO; @Basic @Column(name = "USERNAME") protected String username; @Basic @Column(name = "PASSWORD_HASH") protected String passwordHash; @Basic @Column(name = "EMAIL") protected String email; @Temporal(TemporalType.TIMESTAMP) @Column(name = "REGISTER_DATE") protected Date registerDate; @Temporal(TemporalType.TIMESTAMP) @Column(name = "LAST_LOGIN_DATE") protected Date lastLoginDate;

}

Ответы [ 2 ]

25 голосов
/ 23 июля 2010

Hibernate часто откладывает обновления, пока сеанс не сбрасывается.Чтобы проверить, является ли это проблемой в вашем случае, вставьте getSession().flush() после заявления об обновлении.

Как вы управляете транзакциями?Сброс будет происходить автоматически при фиксации сеанса, но если у вас неправильная конфигурация транзакции, вы можете в конечном итоге зафиксировать соединение JDBC, но не зафиксировать транзакцию, привязанную к сеансу Hibernate.

Редактировать: На основании вашего обновления я вижу, что FlushMode установлен НИКОГДА в какой-то строке:

[TRACE] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1316): setting flush mode to: NEVER

Я подозреваю, что это проблема.Это приводит к тому, что сеанс никогда не сбрасывается автоматически - что обычно требуется делать в транзакции только для чтения, а не при изменении данных.Похоже, что вы работаете без транзакций (для autocommit установлено значение true, что, кстати, не рекомендуется).Javadoc для OpenSessionInViewFilter предоставляет некоторые подсказки:

Этот фильтр по умолчанию не сбрасывает сеанс Hibernate, для режима сброса установлено значение FlushMode.NEVER.Предполагается, что он будет использоваться в сочетании с транзакциями уровня обслуживания, которые заботятся о сбросе: активный менеджер транзакций временно изменит режим очистки на FlushMode.AUTO во время транзакции чтения-записи, с сбросом режима очистки на FlushMode.NEVER в конце.каждой транзакции.Если вы собираетесь использовать этот фильтр без транзакций, рассмотрите возможность изменения режима сброса по умолчанию (через свойство "flushMode").

Другими словами, у вас есть два варианта: либо установить flushMode на своемОткройте OpenSessionInViewFilter для AUTO или отключите автоматическую фиксацию и настройте менеджер транзакций, например HibernateTransactionManager .

6 голосов
/ 23 июля 2010

Поскольку вы используете Spring, я бы порекомендовал вам использовать Spring PlatformTransactionManager для управления своими транзакциями. В рамках управления транзакциями Spring автоматически сбрасывает сессию. Это означает, что вам не нужно беспокоиться о любом из этих аспектов в вашем коде.

Spring имеет OpenSessionInViewFilter, который подключается к менеджеру транзакций для запуска / сброса сеансов, и вы можете аннотировать свои методы с помощью SpringT @Transactional, чтобы указать, что вы хотите транзакцию «записи» для определенного метода. Это должно обновить ваши записи.

...