【问题标题】:Hibernate is not updating record - WicketHibernate 没有更新记录 - Wicket
【发布时间】:2010-07-22 21:03:44
【问题描述】:

我正在使用 Wicket、Spring 和 Hibernate 开发一个 Web 应用程序,但我遇到了更新记录的问题。我已经验证调用了 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
hibernate.cache.use_query_cache=true hibernate.cache.use_second_level_cache=true hibernate.cache.provider=org.hibernate.cache.HashtableCacheProvider
hibernate.schemaUpdate=true

这是 applicationContext.xml 中的 sessionFactory bean:

<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>
</list> </property> <property name="schemaUpdate" value="${hibernate.schemaUpdate}"/> </bean>

希望你们中的一个可以帮助我。

更新这是日志中的一些信息(onSubmit() 会在日志中设置这些条目——最后一个条目应该是请求被重定向到另一个页面时(在记录应该有已更新)。

[调试] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.lookupSessionFactory(OpenSessionInViewFilter.java:239):为 OpenSessionInViewFilter 使用 SessionFactory 'sessionFactory' [调试] 2010-07-23 00:29:26,302 :org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:214):返回单例 bean 'sessionFactory' 的缓存实例 [调试] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:181):在 OpenSessionInViewFilter 中打开单个休眠会话 [调试] 2010-07-23 00:29:26,302 :org.springframework.orm.hibernate3.SessionFactoryUtils.doGetSession(SessionFactoryUtils.java:318):打开休眠会话 [调试] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.(SessionImpl.java:247):在时间戳打开会话:5242215490777088 [TRACE] 2010-07-23 00:29:26,303 :org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1316):将刷新模式设置为:从不 [调试] 2010-07-23 00:29:26,305 :org.apache.wicket.Session.getPage(Session.java:700): 获取页面 [path = 4:userprofile_form, versionNumber = 0] [调试] 2010-07-23 00:29:26,306 :org.apache.wicket.markup.html.form.persistence.CookieValuePersister.getCookie(CookieValuePersister.java:210):找不到名称为 userprofile_form.email 的 Cookie 和请求 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):分离实例:com.upbeat.app.skuldweb.domain.UserVO [TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228):更新分离的实例 [TRACE] 2010-07-23 00:29:26,308 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295):更新 [com.upbeat.app.skuldweb.domain.UserVO#1] [TRACE] 2010-07-23 00:29:26,310:org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346):更新 [com.upbeat.app.skuldweb.domain.UserVO#1] [TRACE] 2010-07-23 00:29:26,311 :org.hibernate.engine.Cascade.cascade(Cascade.java:138):处理级联 ACTION_SAVE_UPDATE 为:com.upbeat.app.skuldweb.domain.UserVO [TRACE] 2010-07-23 00:29:26,312:org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:239):级联到 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):分离实例:com.upbeat.app.skuldweb.domain.UserLevelVO [TRACE] 2010-07-23 00:29:26,312 :org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:228):更新分离的实例 [TRACE] 2010-07-23 00:29:26,313:org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:295):更新 [com.upbeat.app.skuldweb.domain.UserLevelVO#1] [TRACE] 2010-07-23 00:29:26,313:org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:346):更新 [com.upbeat.app.skuldweb.domain.UserLevelVO#1] [TRACE] 2010-07-23 00:29:26,313 :org.hibernate.engine.Cascade.cascade(Cascade.java:173):完成处理级联 ACTION_SAVE_UPDATE 为:com.upbeat.app.skuldweb.domain.UserVO [调试] 2010-07-23 00:29:26,314 :org.apache.wicket.RequestCycle.setRequestTarget(RequestCycle.java:644):替换请求目标 org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget@ 676067951[页面 class= com.upbeat.app.skuldweb.web.user.UserProfilePage,id = 4,版本 = 0]->userprofile_form->interface org.apache.wicket.markup.html.form.IFormSubmitListener.IFormSubmitListener(请求参数:[RequestParameters componentPath=4:userprofile_form pageMapName=null versionNumber=0 interfaceName=IFormSubmitListener componentId=null behaviorId=null urlDepth=-1 参数={email=john@upbeat.no,userprofile__form2_hf_0=} onlyProcessIfPathActive=false]) 与 [BookmarkablePageRequestTarget @1030849724 pageClass=com.upbeat.app.skuldweb.web.user.UserProfilePage]

更新 2 这是没有 getter/setter 的 UserVO

@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 {

@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;

}

【问题讨论】:

    标签: java hibernate wicket


    【解决方案1】:

    Hibernate 通常会推迟更新,直到会话刷新。要测试这是否是您的问题,请在更新语句后插入 getSession().flush()

    您如何管理交易?提交会话时会自动进行刷新,但如果您有错误的事务配置,您最终可能会提交 JDBC 连接,但不会提交与 Hibernate 会话相关的事务。

    编辑:根据您的更新,我看到 FlushMode 在某行设置为 NEVER:

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

    我怀疑这是问题所在。它会导致会话永远不会自动刷新——这通常是你在只读事务中想要做的,而不是在你修改数据时。似乎您在没有事务的情况下运行(自动提交设置为 true - 顺便说一下不推荐)。 OpenSessionInViewFilter 的 Javadoc 提供了一些线索:

    默认情况下,此过滤器不会刷新 Hibernate 会话,刷新模式设置为 FlushMode.NEVER。它假设与关心刷新的服务层事务结合使用:活动事务管理器将在读写事务期间临时将刷新模式更改为 FlushMode.AUTO,最后刷新模式重置为 FlushMode.NEVER每笔交易。如果您打算在没有事务的情况下使用此过滤器,请考虑更改默认刷新模式(通过“flushMode”属性)。

    换句话说,您有两个选择:将 OpenSessionInViewFilter 上的 flushMode 设置为 AUTO,或者关闭自动提交并配置事务管理器,例如 HibernateTransactionManager

    【讨论】:

    • 非常感谢!将 getSession().flush() 添加到更新方法确实有效。我确实尝试在 OpenSessionInViewFilter 中将 flushMode 设置为“AUTO”,但我仍然必须手动调用 getSession().flush() 来运行更新(开启和关闭自动提交)。
    • 将 flushMode 设置为 AUTO 并禁用自动提交后,我可以通过这样做来使其工作;交易 tr = getSession().beginTransaction(); getSession().update(vo); tr.commit();。再次感谢
    【解决方案2】:

    由于您使用的是 Spring,我建议您使用 Spring 的 PlatformTransactionManager 来管理您的事务。作为事务管理的一部分,Spring 会自动刷新会话。这意味着您不必担心代码中的任何这些方面。

    Spring 有一个 OpenSessionInViewFilter,它连接到事务管理器以启动/刷新会话,您可以使用 Spring 的 @Transactional 注释您的方法,以指示您想要为特定方法“写入”事务。这应该会更新您的记录。

    【讨论】:

      猜你喜欢
      • 2018-02-04
      • 2012-04-07
      • 1970-01-01
      • 2016-07-08
      • 2021-01-21
      • 1970-01-01
      • 2017-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多