Как предотвратить дублирование записей во время обновления?

у меня есть index.jsp страница, где у меня есть форма, где пользователь вводит некоторые данные, которые хранятся в базе данных с помощью контроллера-сервлета.

Я хочу отобразить ту же страницу (index.jsp) с этой формой после ввода данных в базу данных. Кроме того, я хочу, чтобы отобразить все записи, которые пользователь ввел в базу данных.

Я попытался с помощью forward() метод RequestDispatcher. Он отлично работает (это означает, что я могу снова отобразить ту же форму, а также отобразить все данные, введенные этим пользователем под формой с помощью JSTL).

но проблема в том, когда пользователь нажимает Refresh or F5 кнопка, все предыдущие данные также вводятся в базу данных, и поскольку я отображаю все данные, и эти дубликаты также появляются.

Я думал об использовании шаблона POST-REDIRECT-GET, но проблема в том, что при перенаправлении я не получаю эти данные для отображения с помощью JSTL.

как мне это сделать?

4 ответов


Я думал об использовании шаблона POST-REDIRECT-GET, но проблема в том, что когда я перенаправляю, я не получаю эти данные для отображения с помощью JSTL.

просто отправьте параметр запроса вместе с идентификацией информации, которую вы хотите отобразить в новом запросе GET.

// ...
Long id = dataService.save(data);
// ...
response.sendRedirect(request.getContextPath() + "/index?editId=" + id);

а потом в сервлет который отображается на шаблоне URL /index

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Long editId = Long.valueOf(request.getParameter("editId")); // Handle nullcheck yourself.
    Data editData = dataService.find(editId);
    request.setAttribute("editData", editData); // For the edit form.
    List<Data> allData = dataService.list();
    request.setAttribute("allData", allData); // For the table/list of all data.
    request.getRequestDispatcher("/index.jsp").forward(request, response);
}

Я бы добавил невидимый идентификатор на страницу. Если данные являются новыми для базы данных (ID = неизвестно), вставьте и создайте ID и обновите страницу с ID. Таким образом, вы знаете, если это ID != неизвестно, и вам не нужно делать вставку. И если данные не изменились, вам даже не придется делать обновление...


вот самое простое решение

<%@page import="java.util.*"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%!
//This List is just for demonstration purposes
List<String> names = new ArrayList<String>();
%>
<%
if(request.getParameter("name")!=null ){
    names.add(request.getParameter("name"));
    session.setAttribute("nameList", names);
    //Here you put your database insert code

    //Whenever the code execution reaches this line , 
    //then it means that you have a new page submission
    //and not a refresh or f5 case

    response.sendRedirect("index.jsp");
}
%>

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <form action="index.jsp" method="post">
            <input type="text" id="name" name="name"/>
        </form>
        <p>
            <table>
                <c:forEach items="${nameList}" var="element">    
                    <tr>
                        <td>Name:  <c:out value="${element}"/> </td>
                    </tr>
                </c:forEach>
            </table>
        </p>
    </body>
</html>

фокус заключается в response.sendRedirect("index.jsp");. Это делает null параметры запроса. Если f5 или refresh попадает, затем if никогда не выполняется. Если обычный submit имеет место, то if выполняется и вы вызываете response.sendRedirect("index.jsp");.

в общем, все, что вам действительно нужно сделать, это:

1) Проверить if(request.getParameter("name")!=null )

2) Если выше верно, то сделайте вставки базы данных

3) Если выше верно тогда response.sendRedirect("index.jsp");

обновление

if(request.getParameter("name")!=null ){
    DbUtility.addNameToDb(request.getParameter("name"));
    ArrayList<String> currentList = DbUtility.getAllNamesFromDb();
    session.setAttribute("nameList", currentList);
    response.sendRedirect("index.jsp");
}

вам просто нужно реализовать эти 2 метода. The addNameToDb(String) сделает insert в вашей базе данных. И getAllNamesFromDb() возвращает ArrayList<String> объект, который будет представлять записи из вашей базы данных. (И вам больше не нужно names список, представленный ранее в моем первом ответе)


Я думаю, что PRGP (Post Redirect Get Pattern) - это способ пойти на это. Если вы используете Spring Web Flow, у него есть FlashScope, где вы можете поместить данные, которые хотите сохранить после перенаправления Post-get. С помощью этого подхода можно сохранить не только идентификатор редактирования.