update the nested object within struts2
With struts2,it will automaticlly create the bean in our action through the ognl,it is easy to use it when we create a new object,for example,in user register page,we build a form for use to fill their information,and in the action we get the properties populated bean,we can save it directly(maybe need some validation),it is so easy.
But how about update a existed object in the db?
We can build a form,(prepopulate the properties that can be updated in the page),when user make some modifination,we update it.
But the bean we get in the action is created by struts2(we call this bean as bean_struts2),and what we want to updated is in the db(we call this bean bean_db).
Now the problem is how to copy the modifinations of the bean_struts2 to bean_db?
For a non-nested object,we can iterator all the properties of the bean_struts2,and set it to bean_db.
For example:
bean_db.setPassword(bean_struts2.getPassword());
.....
But it does not so easy when the bean to be updated is a nested object.
In my case,these are the entities:
class Task{
Object non_updatedProperty;
List<TaskSteps> steps;
List<User> managers;
User publisher;
}
class User{
id,name;
}
class TaskStep{
id,name;
List<Operator> operators;
TaskStepStatus status;
}
enum TaskStepStatus{
ongoing,completed.
}
class Operator{
id,name;
}
The bean to be updated is the "Task" object.
In the page:
<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 value="%{task.publisher.name}" readonly="true" label="Publisher"></s:textfield>
<s:textfield name="task.name" value="%{task.name}" label="Task Name"/>
<table>
<caption align="left">Steps</caption>
<tr>
<th>Step Name</th>
<th>Operators</th>
<开发者_运维技巧th>Status</th>
<th>Set order</th>
<th><span id="addStep" style="cursor:pointer" >Add a step</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"/>
</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.zjswkj.location.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>
</table>
</s:form>
Through struts2,I can get the bean_strtus2(Task),its id is the same as the bean_db. I can easily copy its non-nested propertis to the bean_db. but how about the propertis of its TaskSteps and the operators of its TaskSteps.
Just use :
task_db.setTaskSteps(task_struts2.getTaskSteps());??
Of course not,this may cause some new TaskStep with the same name persisited to the db.
Also,there are some properties can not be updated,for example,the Task's "non_updatedProperty" property can not be updated,it can only be set when the task are created.
So in the update form,I did not provide a UI to update this property,so if we call:
task_db.setNon_updateProperty(task_struts2.getNon_updateProperty);
will miss the exist property,beacuse
task_struts2.getNon_updateProperty==null; !!!
I just wonder if there are some good ideas to handle these types of update?
I am not exactly sure if you guys know what I am meaning,but I have try my best to express it.
If there are more questions,I can update it still.
About the question of transferring efficiently informations from a "structure" (a nested set of beans) managed at the presentation layer (so to say here, populated by Struts2) to another "structure" at the service or the "DB" level, I suggest to have a serious look at http://dozer.sourceforge.net
About the problem of passing on value modification of a "structure" from then to the DB through the presentation layer, it highly depends on the way you map your DB tables (I suppose you're using some kind of relational database) to objects.
When using Hibernate for instance, it is sometimes possible to simply create POJO straight out from your presentation beans, and tell hibernate to "store it"; Hibernate would create / update / delete appropriate records in the table according to the passed structure. Although most of the times there is no silver bullet, and some kind of structure comparison between the structure mapped from DB content and the structure mapped from the presentation layer (through dozer for example) is required to guess what has to be added, modified or deleted.
精彩评论