使用struts2和hibernate更新实体时获取NonUniqueObjectException

时间:2011-03-27 01:49:12

标签: hibernate struts2

我使用hibernate作为ORM框架,这是我第一次用它来编写操作。

对于这个应用程序,我只是使用hibernate从db中读取数据。

在我的struts操作中,我尝试更新名为“Task”的实体,这是更新页面中的表单:

<s:form action="task_update" namespace="/common" cssStyle="width:95%">
    <s:textfield value="%{task.id}" cssStyle="display:none" name="task.id"></s:textfield>
    <s:textfield name="task.name" value="%{task.name}" label="TaskName"/>

    <s:select list="task.managers" 
        listKey="id" listValue="name" label="Manager" value="%{task.manage}" name="task.department.id">
    </s:select>

    <s:select list="#session.current_user.departments" 
        listKey="id" listValue="name" label="Departmentn of this task" value="%{task.department.{id}}" name="task.department.id">
    </s:select>
    <table>
        <caption align="left">Steps</caption>
        <tr>
            <th>Name</th>
            <th>End Time</th>
            <th>Operators</th>
            <th>Status</th>
            <th>Set the order</th>
            <th><span id="addStep" style="cursor:pointer" >Add Steps</span></th>
        </tr>
        <s:iterator value="task.steps">
            <tr class="step">
                <td>
                    <s:textfield name="task.steps[0].name" value="%{#this.name}" theme="simple"/>
                    <s:textfield name="task.steps[0].id" value="%{#this.id}" theme="simple" cssStyle="display:none"/>
                    <s:textfield name="task.steps[0].position" value="%{#this.position}" theme="simple" cssStyle="display:none" class="position"/>
                </td>
                <td><s:textfield name="task.steps[0].end" value="%{#this.end}" theme="simple"/></td>
                <td>        
                    <s:select list="allOpIndb"  listKey="id" listValue="name" value="%{#this.operator.{id}}"
                        name="task.steps[0].operator.id" multiple="true" theme="simple" id="a">
                    </s:select>
                </td>
                <td>
                    <s:select list="@com.infomanager.entity.TaskStepStatus@values()"  theme="simple" 
                        name="task.steps[0].status" listValue="cnValue" value="%{#this.status}" id="b"/>
                </td>
                <td>
                    <span class="up">up</span>
                    <span class="down">down</span>
                    <span class="del">del</span>
                </td>
                <td></td>
            </tr>
        </s:iterator>
        <tr>
            <td colspan="6">
                <s:submit value="Submit"></s:submit>
            </td>
        </tr>
    </table>
</s:form>

可以找到此页面的完整代码here

然后在struts2操作中,我获取struts2创建的任务对象(以下示例中的“task”对象),并在db中找到正在更新的对象(以下示例中的“task_db”对象):

public String task_update{
    DozerBeanMapper dbm = new DozerBeanMapper();
    // the 'task' object is created by struts2
    taskid = task.getId();
    String name_st = task.getName();
    int dep_id_st = task.getDepartment().getId();
    List<TaskStep> steps_st = task.getSteps();

    TaskDaoImpl tkDao = new TaskDaoImpl();
    TaskStepDaoImpl tsDao = new TaskStepDaoImpl();
    OperatorDaoImpl opDao = new OperatorDaoImpl();
    DepartmentDaoImpl depDao = new DepartmentDaoImpl();

    List<TaskStep> step_db = new ArrayList<TaskStep>();
    for (TaskStep step_st : steps_st) {
        int tsid = step_st.getId();
        TaskStep ts_db = tsDao.queryStepById(tsid);
        if (ts_db == null) {
            ts_db = step_st;
        } else
            dbm.map(step_st, ts_db);
        // sest the operators
        List<Operator> ops_to_db = new ArrayList<Operator>();
        for (Operator op_st : step_st.getOperator()) {
            ops_to_db.add(opDao.queryOperatorById(op_st.getId()));
        }
        ts_db.setOperator(ops_to_db);
        step_db.add(ts_db);
    }
    //set the id of the task have the same id with task_db,so set its id to a unimpossible value
    task.setId(-100);
    //set it to null!
    task=null;
    Task task_db = tkDao.queryTaskById(taskid);
    task_db.setName(name_st);
    task_db.setDepartment(depDao.queryDepartById(dep_id_st));
    task_db.setSteps(step_db);

    tkDao.updateTask(task_db);
}

当我提交表单时,我收到了“org.hibernate.NonUniqueObjectException:”: 具有相同标识符值的不同对象已与会话关联:[com.infomanager.entity.Task#4]。

我想知道为什么?我已将任务的id设置为-100,并将其设置为null。

有什么问题?

以下是我的数据库中tabl的realation ship: enter image description here

整个项目可以在这里找到:https://github.com/hguser/TaskManager

1 个答案:

答案 0 :(得分:0)

基本上,hibernate所说的是你有两个具有相同标识符的对象(相同的主键),但它们不是同一个对象。

按照这篇文章可能会对你有帮助。 NonUniqueObjectException

只有在hibernate在会话上下文中找到具有相同标识符的两个对象时才会出现此异常。