0

在带有 Hibernate 4.1 的 Spring 3.1 MVC 应用程序中,场景是:

  • 网页显示记录列表,用户可以在其中使用复选框选择记录
  • 在 POST 时,选定的记录将被删除

由于此功能也出现在其他地方,我想使用泛型以避免复制类似的代码。

逻辑是:

  • 在 GET 上,我使用包含休眠对象和布尔值的泛型填充一个列表,并将该列表添加到模型中
  • 在 POST 上,我从模型中获取该列表并将其传递给服务以删除选定的记录

代码是:

/* 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 项”的类型为“MyDomainObject”。

在 POST 时,“T 项目”的类型为“java.lang.Object”,当执行“sessionFactory.getCurrentSession().delete(item.getItem())”时,我得到“org.hibernate.MappingException: Unknown实体:java.lang.Object"

有人可以解释一下是什么原因造成的以及如何解决吗?

先感谢您。

4

2 回答 2

0

Hibernate 做了“一些神奇的事情”,并且经常使用反射来访问变量并确定类型。这些类型对于 Hibernate 决定使用哪个映射很重要。

在获取请求中,您提供MyDomainObject.class了正确的类。这似乎足以让 Hibernate 找到映射。

发布请求不是这种情况。语句中的 Hibernatedelete(item.getItem())只获取信息getItem()返回一个对象(类型T由于类型擦除而被删除并且不适用于 Hibernate)。信息“对象”不允许 Hibernate 找到item.

您可以尝试将项目转换为喜欢delete((MyDomainObject)item.getItem())或先将其放入类型良好的变量中

   MyDomainObject mdoItem = item.getItem();
   sessionFactory.getCurrentSession().delete(mdoItem);

(我不确定这两种可能性中的哪一种会起作用。)

于 2012-05-30T16:25:03.693 回答
0

正如我所提到的,问题出在 POST 时返回 @ModelAttribute("selectionListCommand") 时。

解决方案是:

  • 添加到控制器 -> @SessionAttributes("selectionListCommand")
  • 修改类 SelectionList 为 ->公共类 SelectionList 实现 java.io.Serializable

我希望这将在未来节省别人的时间。

于 2012-06-01T15:45:57.787 回答