在使用Hibernate 4.1的Spring 3.1 MVC应用程序中,场景是:
由于此功能也出现在其他地方,我想使用泛型以避免复制类似的代码。
逻辑是:
代码是:
/* list item */
public class SelectionListItem<T> {
/* holds the hibernate object */
private T item;
/* whether the record is selected */
private boolean selected;
public SelectionListItem() {
}
public SelectionListItem(T item, boolean selected) {
this.item = item;
this.selected = selected;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
/* list that holds the records */
public class SelectionList<T> {
private List<SelectionListItem<T>> list = new ArrayList<SelectionListItem<T>>();
public SelectionList() {
}
public List<SelectionListItem<T>> getList() {
return list;
}
public void setList(List<SelectionListItem<T>> list) {
this.list = list;
}
}
/* Controller for GET */
@RequestMapping(value = "/xxx", method = RequestMethod.GET)
public String functionGET(Model model) {
// Retrieve data from database and prepare the list
SelectionList<MyDomainObject> selectionList = someService.getRecordsAndPrepareList();
// Add command object to model
model.addAttribute("selectionListCommand", selectionList);
return "xxx";
}
/* Service that retrieves the records and prepares the list */
public SelectionList<MyDomainObject> getRecordsAndPrepareList() {
List<MyDomainObject> result = sessionFactory.getCurrentSession().createCriteria(MyDomainObject.class).list();
SelectionList<MyDomainObject> selectionList = new SelectionList<MyDomainObject>();
for (MyDomainObject item : result) {
SelectionListItem<MyDomainObject> e = new SelectionListItem<MyDomainObject>(item, false);
selectionList.getList().add(e);
}
return selectionList;
}
/* Controller for POST */
@RequestMapping(value = "/xxx", method = RequestMethod.POST)
public String functionPOST(
@ModelAttribute("selectionListCommand") SelectionList<MyDomainObject> selectionListCommand,
BindingResult result, Model model) {
// Delete record
someService.deleteSelectedRecords(selectionListCommand);
return "xxx;
}
/* Service that deletes the selected records*/
public void deleteSelectedRecords(SelectionList<MyDomainObject> selectionList) {
for (SelectionListItem<MyDomainObject> item : selectionList.getList()) {
if (item.isSelected()) {
sessionFactory.getCurrentSession().delete(item.getItem());
}
}
}
在GET请求时,SelectionList被正确填充,“T item”的类型为“MyDomainObject”。
在POST时,“T item”的类型为“java.lang.Object”,当执行“sessionFactory.getCurrentSession()。delete(item.getItem())”时,我得到“org.hibernate”。 MappingException:未知实体:java.lang.Object“
有人可以解释导致它的原因以及解决方法吗?
提前谢谢。
答案 0 :(得分:0)
Hibernate做“一些神奇的事情”,并经常使用反射来访问变量并确定类型。这些类型对于Hibernate决定使用哪个映射非常重要。
在get请求中,您提供了MyDomainObject.class
正确的类。这似乎足以让Hibernate找到映射。
发布请求不是这种情况。声明delete(item.getItem())
中的Hibernate只获取信息getItem()
返回一个对象(由于类型擦除而导致类型T
被删除,而Hibernate不可用)。信息“对象”不允许Hibernate查找item
的映射。
您可以尝试投放像delete((MyDomainObject)item.getItem())
这样的项目,或者先将其放入一个输入良好的变量中
MyDomainObject mdoItem = item.getItem();
sessionFactory.getCurrentSession().delete(mdoItem);
(我不确定这两种可能性中哪一种可行。)
答案 1 :(得分:0)
正如我所提到的,问题是在POST时返回了@ModelAttribute(“selectionListCommand”)。
解决方案是:
我希望将来可以节省别人的时间。