Я использую hibernate в качестве фреймворка ORM, и я впервые использую его для операций записи.
Для этого приложения я просто использую hibernate для чтения данных из БД.
В своем действии Struts я пытаюсь обновить объект с именем «Задача», это форма на странице обновления:
<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>
Полные коды этой страницы можно найти здесь :
Затем в действии struts2 я получаю объект задачи, созданный struts2 (объект «задача» в следующем примере), и нахожу обновляемый объект в базе данных (объект «задача_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].
Интересно, почему?Я установил идентификатор задачи равным -100, и установил его на ноль.
В чем проблема?
Ниже приведено описание корабля таблиц в моей БД:
А весь проект можно найти здесь: https://github.com/hguser/TaskManager