Spring MVC - 提交后子实体丢失
我将尝试尽可能完整、简短地解释我的问题...
一个 Web 应用程序,在 Spring MVC 2.5 + Hibernate + Java 6 上制作(不使用注释!)。
我有一个扩展 SimpleFormController 的控制器和一个 jsp 页面,即它的 formView 和 successView。
这个控制器应该帮助我将一个实体 PracticeT 插入到数据库中,该实体已连接(多对一)一个查找实体 PracticeConfT (将其视为“类型学”)。我需要通过下拉菜单选择该“类型”。在我的网络应用程序中,我需要能够保存插入的数据,并在需要时提交批准请求。
该页面有一些文本字段和下拉菜单。被称为默认“命令”的 bean 是 NewPracticeBean,它包含对对象 PracticeT 的引用。
问题是:我填写表单,从下拉菜单中选择类型,提交表单并将数据保存在数据库上,但是当我返回视图时,每个属性都在那里,但下拉菜单不存在:它具有所有允许的选项,但没有选择任何一个。一些检查显示实体 PracticeConfT 为空(但它已正确记录在数据库上,并且调试它仍然存在于模型中,直到方法 onSubmit 结束!!!)。
我希望有人能帮助我。先感谢您! 再见, Dolfiz
这里有一些有用的代码: (我不认为 hibernate 配置可能是问题,但如果你需要它,我也可以发布它)
newPractice.jsp
<form:form id="newPracticeForm" commandName="command">
<input type="hidden" name="action"/>
<spring:nestedPath path="practiceT">
<table class="table-data-form">
<tr>
<td class="left"><spring:message code="" text="Practice type" /></td>
<td>
<form:select path="practiceConfT" multiple="false">
<form:option value="" label="- seleziona -"/>
<form:options items="${practiceTypeList}" itemValue="idPracticeConf" itemLabel="practiceName"/>
</form:select>
</td>
</tr>
<tr>
<td class="left">
<spring:message code="" text="Opzione divisa" />
<br/><form:errors cssClass="errors" path="opzioneDivisa" />
</td>
<td><form:input path="opzioneDivisa" /></td>
</tr>
<tr>
<td colspan="1">
<input type="submit" name="submit" id="submit" value="Save" class="buttonEMS" style="width:100px;" />
</td>
</tr>
</table>
</spring:nestedPath>
</form:form>
NewPracticeBean.java
public class NewPracticeBean implements Serializable{
private PracticeT practiceT;
private String action;
private boolean typeSelected;
public NewPracticeBean(){
super();
this.practiceT = new PracticeT();
}
// getters & setters...
}
PracticeT .java
public class PracticeT implements java.io.Serializable {
private long idPractice;
private PracticeConfT practiceConfT;
private String opzioneDivisa;
// getters & setters...
}
PracticeConfT.java
public class PracticeConfT implements java.io.Serializable {
public static final String PRACTICE_NAME = "practiceName";
private long idPracticeConf;
private String practiceName;
// getters & setters...
}
NewPracticeController.java 公共类 NewPracticeController 扩展 SimpleFormController{
protected SmartLogger log = SmartLogger.getLogger(this.getClass());
private PracticeSu practiceSu;
private ConfigurationSu configurationSu;
private HibernateEntityDataBinder practiceConfTBinder;
private HibernateEntityDataBinder practiceTBinder;
public NewPracticeController() {
setCommandClass(NewPracticeBean.class);
setCommandName("command");
}
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
log.trace("NewPracticeController -- initBinder");
super.initBinder(request, binder);
binder.registerCustomEditor(PracticeT.class, "practiceT", practiceTBinder);
binder.registerCustomEditor(PracticeConfT.class, "practiceT.practiceConfT", practiceConfTBinder);
}
@Override
protected Map referenceData(HttpServletRequest request) throws Exception {
log.trace("NewPracticeController -- referenceData");
Map model = new HashMap();
RetrieveAllEntitiesReq req = new RetrieveAllEntitiesReq();
req.setEntity(PracticeConfT.class);
req.setOrderProperty(PracticeConfT.PRACTICE_NAME);
RetrieveAllEntitiesResp resp = configurationSu.retrieveAllEntities(req);
List entitiesList = resp.getEntitiesList();
model.put("practiceTypeList", entitiesList);
return model;
}
@Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
NewPracticeBean practiceBean = (NewPracticeBean)command;
Map model = errors.getModel();
CreateNewPracticeReq req = new CreateNewPracticeReq();
req.setPracticeT(practiceBean.getPracticeT());
CreateNewPracticeResp resp = practiceSu.createNewPractice(req);
practiceBean.setPracticeT(resp.getPracticeT());
model.putAll(referenceData(null));
model.put(getCommandName(), practiceBean);
return new ModelAndView(getSuccessView(), model);
}
// setters and getters...
}
I'm going to try to explain my problem as completely and shortly as I can...
A web application, made on Spring MVC 2.5 + Hibernate + Java 6 (not using annotation!).
I've got a controller extending SimpleFormController and a jsp page that is its formView and successView.
This controller should help me to insert into db an entity PracticeT that has connected (many to one) a lookup entity PracticeConfT (think about it as a "typology"). I need to choose that "typology" through a drop-down menu. In my webapp I need to be able to save data inserted and when I want, to submit the request for approval.
The page has some text fields and that drop-down menu. The bean called as default "command" is NewPracticeBean that has within a reference to an object PracticeT.
THE PROBLEM IS: I fill the form, I select a typology from the drop-down menu, I submit form and save data on DB but when I come back to the view, every property is there but the drop-down menu it is not: it has all the options allowed but no one selected. Some checks revealed that the entity PracticeConfT is null (but it has been recorded on db correctly and debugging it is still there in the model until the very end of the method onSubmit!!!).
I hope someone can help me. Thank you in advance!
Bye,
Dolfiz
Here some useful code:
(I don't think that hibernate config can be the problem, but if you need it, I can post it too)
newPractice.jsp
<form:form id="newPracticeForm" commandName="command">
<input type="hidden" name="action"/>
<spring:nestedPath path="practiceT">
<table class="table-data-form">
<tr>
<td class="left"><spring:message code="" text="Practice type" /></td>
<td>
<form:select path="practiceConfT" multiple="false">
<form:option value="" label="- seleziona -"/>
<form:options items="${practiceTypeList}" itemValue="idPracticeConf" itemLabel="practiceName"/>
</form:select>
</td>
</tr>
<tr>
<td class="left">
<spring:message code="" text="Opzione divisa" />
<br/><form:errors cssClass="errors" path="opzioneDivisa" />
</td>
<td><form:input path="opzioneDivisa" /></td>
</tr>
<tr>
<td colspan="1">
<input type="submit" name="submit" id="submit" value="Save" class="buttonEMS" style="width:100px;" />
</td>
</tr>
</table>
</spring:nestedPath>
</form:form>
NewPracticeBean.java
public class NewPracticeBean implements Serializable{
private PracticeT practiceT;
private String action;
private boolean typeSelected;
public NewPracticeBean(){
super();
this.practiceT = new PracticeT();
}
// getters & setters...
}
PracticeT.java
public class PracticeT implements java.io.Serializable {
private long idPractice;
private PracticeConfT practiceConfT;
private String opzioneDivisa;
// getters & setters...
}
PracticeConfT.java
public class PracticeConfT implements java.io.Serializable {
public static final String PRACTICE_NAME = "practiceName";
private long idPracticeConf;
private String practiceName;
// getters & setters...
}
NewPracticeController.java
public class NewPracticeController extends SimpleFormController{
protected SmartLogger log = SmartLogger.getLogger(this.getClass());
private PracticeSu practiceSu;
private ConfigurationSu configurationSu;
private HibernateEntityDataBinder practiceConfTBinder;
private HibernateEntityDataBinder practiceTBinder;
public NewPracticeController() {
setCommandClass(NewPracticeBean.class);
setCommandName("command");
}
@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
log.trace("NewPracticeController -- initBinder");
super.initBinder(request, binder);
binder.registerCustomEditor(PracticeT.class, "practiceT", practiceTBinder);
binder.registerCustomEditor(PracticeConfT.class, "practiceT.practiceConfT", practiceConfTBinder);
}
@Override
protected Map referenceData(HttpServletRequest request) throws Exception {
log.trace("NewPracticeController -- referenceData");
Map model = new HashMap();
RetrieveAllEntitiesReq req = new RetrieveAllEntitiesReq();
req.setEntity(PracticeConfT.class);
req.setOrderProperty(PracticeConfT.PRACTICE_NAME);
RetrieveAllEntitiesResp resp = configurationSu.retrieveAllEntities(req);
List entitiesList = resp.getEntitiesList();
model.put("practiceTypeList", entitiesList);
return model;
}
@Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
NewPracticeBean practiceBean = (NewPracticeBean)command;
Map model = errors.getModel();
CreateNewPracticeReq req = new CreateNewPracticeReq();
req.setPracticeT(practiceBean.getPracticeT());
CreateNewPracticeResp resp = practiceSu.createNewPractice(req);
practiceBean.setPracticeT(resp.getPracticeT());
model.putAll(referenceData(null));
model.put(getCommandName(), practiceBean);
return new ModelAndView(getSuccessView(), model);
}
// setters and getters...
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在花了一些时间使用
OptionsTag
、OptionWriter
和SelectValueComparator
后,我想说,“selected”的输出是基于 Object.equals 的。因此,如果出于任何原因(延迟加载...),对象
PracticeT.practiceConfT
和model.put("practiceTypeList",EntityList)
的相应对象不相同( ==) 那么只要 equals 方法没有正确实现,forms:options
就不会选择它们。所以我想你需要实现一个正确的 equals 方法,即使这不能解决这个问题,有一个正确的 equals 方法总是比错误或没有更好。
正确的实现意味着必须注意与Hibernate 一起使用的事实。 (例如使用
if (Hibernate.getClass(this) != Hibernate.getClass(other))
而不是 `if (this.getClass() != other.getClass() )After spending some time with
OptionsTag
,OptionWriter
andSelectValueComparator
, I would say, then output of "selected" is based on Object.equals.So if for any reason (Lazyloading...) the Object
PracticeT.practiceConfT
and the according Objects ofmodel.put("practiceTypeList", entitiesList)
are not the SAME (==) thenforms:options
will not select them as long as the equals method is not correct implemented.So I guess you need to implement a correct equals method, even if this did not fix this problem, it is always better to have a correct equals method than a wrong or none.
Correct implemented means that it must pay attention to the fact that is used with Hibernate. (for example use
if (Hibernate.getClass(this) != Hibernate.getClass(other))
instead of `if (this.getClass() != other.getClass() )