我使用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:
整个项目可以在这里找到:https://github.com/hguser/TaskManager
答案 0 :(得分:0)
基本上,hibernate所说的是你有两个具有相同标识符的对象(相同的主键),但它们不是同一个对象。
按照这篇文章可能会对你有帮助。 NonUniqueObjectException
只有在hibernate在会话上下文中找到具有相同标识符的两个对象时才会出现此异常。