2.3.8. Create a batch update function¶
This section describes the batch update function based on an example application.
- Description of the function to be created
- Click on the batch update (プロジェクト一括更新)link on the menu for transition to the batch update screen.
- Results of all project searches are displayed.
- Rewrite the item to be updated on the relevant page and click the update(更新) button (update across pages is not possible).
- When the update confirmation screen is displayed, click on the confirm(確定) button.
- The database is updated and the update completion screen is displayed.
2.3.8.1. Create a batch update function¶
Describes how to create a bulk update feature.
- Create a form
- Create a bean to pass the update target to the screen
- Create a business action method to display the batch update screen
- Create a batch update screen JSP
- Create a business action method to check the update content
- Create a confirmation screen JSP
- Create a business action method that updates the database in a batch
- Create the completion screen
- Create a form
Create a form to accept search condition and to accept update contents respectively.
- Create a search form
- Refer to create search function:Form creation as the same implementation can be used for the search form.
- Create an update form
Create two types of forms as the update information of multiple projects is sent in a batch.
- A form to accept updates for one project
Create a form that accepts the update value for one project.
- InnerProjectForm.java
public class InnerProjectForm implements Serializable { // Excerpt of some items only /** Project name */ @Required @Domain("projectName") private String projectName; // Getter and setter are omitted }
- Key points of this implementation
- Since Bean Validation is executed even for nested forms, assign annotations for validations such as @Required and @Domain.
- Parent form with a list of forms as properties for a single project
To receive updated information of multiple projects in a batch, create a parent form that defines a list of forms to receive update information for one project.
- ProjectBulkForm.java
public class ProjectBulkForm implements Serializable { /** List of project information */ @Valid private List<InnerProjectForm> projectList = new ArrayList<>(); // Getter and setter are omitted }
- Key points of this implementation
- By assigning @Valid, nested forms can also be included as targets of Bean Validation.
- Create a bean that delivers the update target list acquired with business action to the screen.
Creates a bean that delivers the update target list acquired with business action to the screen. This bean is registered in the session store to be carried through the batch update and confirmation screen.
- ProjectListDto.java
public class ProjectListDto implements Serializable { /** Project list */ private List<Project> projectList = new ArrayList<>(); // Getter and setter are omitted }
- Key points of this implementation
- When registering array or collection type in the session store, it is defined as a serializable Bean property and that Bean is registered in the session store. For more information, see restrictions on the use of the session store.
- Create a business action method to display the batch update screen
Acquire the target project from the database and create a business action method to be displayed on the batch update screen.
- ProjectBulkAction.java
@InjectForm(form = ProjectSearchForm.class, prefix = "searchForm", name = "searchForm") @OnError(type = ApplicationException.class, path = "forward://initialize") public HttpResponse list(HttpRequest request, ExecutionContext context) { ProjectSearchForm searchForm = context.getRequestScopedVar("searchForm"); // Search execution ProjectSearchDto projectSearchDto = BeanUtil.createAndCopy(ProjectSearchDto.class, searchForm); EntityList<Project> projectList = searchProject(projectSearchDto, context); ProjectListDto projectListDto = new ProjectListDto(); projectListDto.setProjectList(projectList); SessionUtil.put(context, "projectListDto", projectListDto); // Pass the update target to the screen context.setRequestScopedVar("bulkForm", projectListDto); // Save the search criteria SessionUtil.put(context, "projectSearchDto", projectSearchDto); return new HttpResponse("/WEB-INF/view/projectBulk/update.jsp"); }
- Key points of this implementation
- Refer to create search function:Business action implementation as the same implementation method can be used for the search method.
- When returning to the batch update screen from the confirmation screen, register and carry out the search conditions in the session store so that paging and re-search is enabled under the same conditions.
- Create a batch update screen JSP
Create a JSP for batch update screen that displays the search results and compiles information of multiple projects.
- /src/main/webapp/WEB-INF/projectBulk/update.jsp
<!-- Display section of customer search result --> <n:form> <!-- Register the URI containing the search conditions used to display the current search results as a variable in the page scope as a variable. This variable is used as URI for the paging of <app:listSearchResult> tag. --> <c:url value="list" var="uri"> <!-- Acquire search criteria from projectSearchDto of the session store --> <c:param name="searchForm.clientId" value="${projectSearchDto.clientId}"/> <c:param name="searchForm.clientName" value="${projectSearchDto.clientName}"/> <c:param name="searchForm.projectName" value="${projectSearchDto.projectName}"/> <!-- Omitted as it is a search condition parameter as well --> </c:url> <app:listSearchResult> <!-- Attribute values of listSearchResult are omitted --> <jsp:attribute name="headerRowFragment"> <tr> <th>Project ID</th> <th>Project name</th> <th>Project type</th> <th>Start date</th> <th>End date</th> </tr> </jsp:attribute> <jsp:attribute name="bodyRowFragment"> <tr class="info"> <td> <!-- Displays the link with project ID as a parameter --> <n:a href="show/${row.projectId}"> <n:write name="bulkForm.projectList[${status.index}].projectId"/> </n:a> <n:plainHidden name="bulkForm.projectList[${status.index}].projectId"/> </td> <td> <div class="form-group"> <n:text name="bulkForm.projectList[${status.index}].projectName" maxlength="64" cssClass="form-control" errorCss="input-error input-text"/> <n:error errorCss="message-error" name="bulkForm.projectList[${status.index}].projectName" /> </div> </td> <!-- Other editing items are omitted --> </tr> </jsp:attribute> </app:listSearchResult> <div class="title-nav page-footer"> <div class="button-nav"> <n:button id="bottomUpdateButton" uri="/action/projectBulk/confirmOfUpdate" disabled="${isUpdatable}" cssClass="btn btn-raised btn-success"> Update</n:button> <n:a id="bottomCreateButton" type="button" uri="/action/project" cssClass="btn btn-raised btn-default" value="New registration"></n:a> </div> </div> </n:form>
- Key points of this implementation
- Refer to create search function: Create a search result display part as the method to create a JSP that displays search results.
- When returning to the batch update screen from the confirmation screen, configure search condition parameters based on the search conditions acquired from session store, so that re-search and paging is enabled under the same conditions. In JSP, objects registered in session store can be handled in the same way as objects registered in the request scope.
- Array type or List type property element can be accessed by the property name[index] format. For more information, see Rules to access input/output data.
- Create a business action method to check the updated contents
Create a business action method to check the updated contents.
- ProjectBulkAction.java
@InjectForm(form = ProjectBulkForm.class, prefix = "bulkForm", name = "bulkForm") @OnError(type = ApplicationException.class, path = "/WEB-INF/view/projectBulk/update.jsp") public HttpResponse confirmOfUpdate(HttpRequest request, ExecutionContext context) { ProjectBulkForm form = context.getRequestScopedVar("bulkForm"); ProjectListDto dto = SessionUtil.get(context, "projectListDto"); // Overwrite updates to session final List<InnerProjectForm> innerForms = form.getProjectList(); dto.getProjectList() .forEach(project -> innerForms.stream() .filter(innerForm -> Objects.equals(innerForm.getProjectId(), project.getProjectId() .toString())) .findFirst() .ifPresent(innerForm -> BeanUtil.copy(innerForm, project))); return new HttpResponse("/WEB-INF/view/projectBulk/confirmOfUpdate.jsp"); }
- Key points of this implementation
- The information to be updated is held in the session store.
- Create a confirmation screen JSP
Create a JSP that displays the changed project information on the screen.
- /src/main/webapp/WEB-INF/projectBulk/confirmOfUpdate.jsp
<section> <div class="title-nav"> <span>Project search list update screen</span> <div class="button-nav"> <n:form useToken="true"> <!-- Button part is omitted --> </n:form> </div> </div> <h4 class="font-group">Project update list</h4> <div> <table class="table table-striped table-hover"> <tr> <th>Project ID</th> <th>Project name</th> <th>Project type</th> <th>Start date</th> <th>End date</th> </tr> <c:forEach var="row" items="${projectListDto.projectList}"> <tr class="<n:write name='oddEvenCss' />"> <td> <n:write name="row.projectId" /> </td> <!-- Other items are omitted --> </tr> </c:forEach> </table> </div> </section>
- Create a business action method that updates the database in a batch
The target project is updated in a batch.
- ProjectBulkAction.java
@OnDoubleSubmission public HttpResponse update(HttpRequest request, ExecutionContext context) { ProjectListDto projectListDto = SessionUtil.get(context, "projectListDto"); projectListDto.getProjectList().forEach(UniversalDao::update); return new HttpResponse(303, "redirect://completeOfUpdate"); }
- Key points of this implementation
The basic implementation method is the same as create an update function: Create business action method to update the database.
Execute UniversalDao#update for the number of updates. When an exclusive control error occurs, all updates are rolled back.
Tip
Since an error control handler is added to the example application, if OptimisticLockException occurs due to an exclusive control error, the screen transitions to the exclusive control error screen. For how to create error control handler, refer to transition to the error page for the exception class with the handler.
Although UniversalDao also provides a UniversalDao#batchUpdate method that takes a list of entities as arguments, method that takes a list of entities as arguments, batch execution and does not perform exclusive control. If exclusive control is required, use UniversalDao#update.
- Display completion screen
- Refer to create an update function: Create update completion screen as the same implementation method can be used for the completion screen.
This completes the description of the batch update function.