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が使用するマッピングを決定するために重要です。

getリクエストではMyDomainObject.class、正しいクラスを提供します。これは、Hibernateがマッピングを見つけるのに十分なようです。

これは、POSTリクエストには当てはまりません。ステートメント内のHibernateは、オブジェクトを返すdelete(item.getItem())情報のみを取得します(型消去のために型が削除され、Hibernateでは使用できません)。情報'オブジェクト'は、Hibernateがのマッピングを見つけることを許可しません。getItem()Titem

のようにアイテムをキャストしdelete((MyDomainObject)item.getItem())たり、最初に適切に型指定された変数に入れたりすることができます

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

(2つの可能性のどちらが機能するかはわかりません。)

于 2012-05-30T16:25:03.693 に答える
0

前述したように、問題は @ModelAttribute("selectionListCommand") が POST で返されたときでした。

解決策は次のとおりです。

  • コントローラーに追加 -> @SessionAttributes("selectionListCommand")
  • クラス SelectionList を次のように変更します -> public クラス SelectionList は java.io.Serializable を実装します

将来、他の誰かの時間を節約できることを願っています。

于 2012-06-01T15:45:57.787 に答える