Spring MVC,从请求生成表单支持对象?
问题内容:
我正在使用Spring MVC 2.5,并且试图从GET请求中加载一个JSTL表单对象。我有Hibernate POJO作为我的支持对象。
在请求中,有一个页面指向具有类ID(行主键)的另一页面。该请求看起来像“ newpage.htm?name =
RowId”。这将进入具有表单支持对象的页面,
上方的新页面将对象的字段加载到可编辑字段中,并填充该行的现有值。想法是,您应该能够编辑这些字段,然后将其持久化回到数据库中。
此页面的视图如下所示
<form:form commandName="thingie">
<span>Name:</span>
<span><form:input path="name" /></span>
<br/>
<span>Scheme:</span>
<span><form:input path="scheme" /></span>
<br/>
<span>Url:</span>
<span><form:input path="url" /></span>
<br/>
<span>Enabled:</span>
<span><form:checkbox path="enabled"/></span>
<br/>
<input type="submit" value="Save Changes" />
</form:form>
控制器里面有这个
public class thingieDetailController extends SimpleFormController {
public thingieDetailController() {
setCommandClass(Thingie.class);
setCommandName("thingie");
}
@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
Thingie thingieForm = (Thingie) super.formBackingObject(request);
//This output is always null, as the ID is not being set properly
logger.debug("thingieForm.getName(): [" + thingieForm.getName() + "]");
//thingieForm.setName(request.getParameter("name"));
SimpleDAO.loadThingie(thingieForm);
return thingieForm;
}
@Override
protected void doSubmitAction(Object command) throws Exception {
Thingie thingie = (Thingie) command;
SimpleDAO.saveThingie(thingie);
}
}
从注释代码中可以看到,我尝试从请求中手动设置对象ID(这种情况下为名称)。但是,当我尝试将数据持久保存在表单中时,Hibernate抱怨该对象被取消同步。
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
该错误似乎对整个会话都起作用,从而使整个Web应用程序停止工作,并不断抛出上面看到的Stale Object State Exception。
如果熟悉Spring MVC的任何人可以帮助我解决这个问题或提出解决方法,我将不胜感激。
编辑:
会话工厂代码。
private static final SessionFactory sessionFactory;
private static final Configuration configuration = new Configuration().configure();
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
问题答案:
使用Spring MVC +
hibernate的主要缺陷之一是自然的方法是使用hibernate域对象作为表单的后备对象。Spring将根据名称通过DEFAULT绑定请求中的任何内容。这无意间包括了诸如ID或名称(通常是主键)或其他hibernate管理属性的设置。这也使您很容易进行表单注入。
为了在这种情况下保持安全,您必须使用类似以下内容的方法:
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
throws Exception {
String[] allowedFields = {"name", "birthday"}
binder.setAllowedFields(allowedFields);
}
并明确地将“允许”字段设置为仅表单中的那些字段,并排除主键,否则您将陷入混乱!!!