简体   繁体   English

JSP页面中的对象在表单中修改时不返回。(数据写入ID为0的新对象)

[英]The object from the JSP page is not returned when it is modified in the form.(data is written to a new object with ID 0)

I pass the ID as a parameter to the edit page, it comes in. In the form, I make changes and when I submit, the POST create a new object and not the one that I edited with the ID passed.我将 ID 作为参数传递给编辑页面,它进来了。在表单中,我进行了更改,当我提交时,POST 创建一个新对象,而不是我使用传递的 ID 编辑的对象。

I've already spent 20 hours trying to solve this problem, but I can't solve it on my own, so I'm asking for your help.我已经花了20个小时试图解决这个问题,但我无法自己解决,所以我请求你的帮助。

exeption stacktrace:异常堆栈跟踪:

HTTP Status 500 – Internal Server Error
Type Exception Report

Message Request processing failed; nested exception is org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Object of class [bookManager.model.Genre] with identifier [0]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [bookManager.model.Genre#0]

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Object of class [bookManager.model.Genre] with identifier [0]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [bookManager.model.Genre#0]
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Object of class [bookManager.model.Genre] with identifier [0]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [bookManager.model.Genre#0]
    org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:286)
    org.springframework.orm.hibernate5.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:798)
    org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:634)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
    org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    com.sun.proxy.$Proxy48.edit(Unknown Source)
    bookManager.controller.GenreController.editGenre(GenreController.java:68)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [bookManager.model.Genre#0]
    org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2522)
    org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3355)
    org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3229)
    org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3630)
    org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
    org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)
    org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)
    org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1454)
    org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:511)
    org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3283)
    org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2479)
    org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473)
    org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178)
    org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39)
    org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271)
    org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:98)
    org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:622)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
    org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    com.sun.proxy.$Proxy48.edit(Unknown Source)
    bookManager.controller.GenreController.editGenre(GenreController.java:68)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
Note The full stack trace of the root cause is available in the server logs.

Class Genre:班级类型:

package bookManager.model;

import org.springframework.transaction.annotation.Transactional;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

/**
 * this simple java bean
 */

@Entity
@Table(name = "genre")
public class Genre {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "genre_name")
    private String genreName;

    @OneToMany(mappedBy = "genre", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Book> books;

    public Genre() {
    }

    public Genre(String genreName) {
        this.genreName = genreName;
        books = new ArrayList<Book>();
    }

    public String getGenreName() {
        return genreName;
    }

    public void setGenreName(String genreName) {
        this.genreName = genreName;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return  genreName;
    }
}

DAO:道:

package bookManager.dao;

import bookManager.model.Genre;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class GenreDAOImpl implements GenreDAO {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory){this.sessionFactory = sessionFactory;}


    @Override
    @SuppressWarnings("unchecked")
    public List<Genre> allGenre() {
        Session session = sessionFactory.getCurrentSession();
        return session.createQuery("from Genre").list();
    }


    @Override
    public void edit(Genre genre) {
        Session session = sessionFactory.getCurrentSession();
        session.update(genre);
    }
}

Service:服务:

package bookManager.service;

import bookManager.dao.GenreDAO;
import bookManager.model.Genre;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class GenreServiceImpl implements GenreService {

    private GenreDAO genreDAO;

    @Autowired
    public void setGenreDAO(GenreDAO genreDAO) {this.genreDAO = genreDAO;}

    @Override
    @Transactional
    public void edit(Genre genre) {
        genreDAO.edit(genre);
    }        

}

Controller:控制器:

package bookManager.controller;

import bookManager.model.Genre;
import bookManager.service.GenreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@Controller
public class GenreController {
    private GenreService genreService;

    @Autowired
    public void setGenreService(GenreService genreService) {this.genreService = genreService;}

    @RequestMapping(value = "/editGenre/{id}", method = RequestMethod.GET)
    public ModelAndView editGenrePage(@PathVariable("id") int id) {
        Genre genre = genreService.getById(id);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("genreEditPage");
        modelAndView.addObject("genre", genre);
        return modelAndView;
    }

    @RequestMapping(value = "/editGenre", method = RequestMethod.POST)
    public ModelAndView editGenre(@ModelAttribute("genre") Genre genre) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:/genre");
        genreService.edit(genre);
        return modelAndView;
    }
}

JSP file: JSP文件:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Изменить жанр</title>
</head>
<body>
<div>
    <h2 class="headline">Изменить жанр</h2>
</div>
<div>
    <c:url value="/editGenre" var="editGenre"/>
    <form action="${editGenre}" method="POST">
        <input type="hidden" name="id" id="id" value="${genre.id}">
        <label for="genreName">Жанр</label>
        <input type="text" name="genreName" id="genreName" value="${genre.genreName}">
        <input type="submit" value="Изменить жанр">
    </form>
</div>
</body>
</html>

JSP conversion page: JSP转换页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <link href="<c:url value="/res/style.css"/>" rel="stylesheet" type="text/css"/>
    <title>Жанры</title>
</head>
<body>

<h2 class="headline">Жанры</h2>
<table>
    <tr>
        <th>id</th>
        <th >Жанр</th>
    </tr>
    <c:forEach var="genres" items="${genreList}">
        <tr>
            <td>${genres.id}</td>
            <td>${genres.genreName}</td>
            <td>
                <a href="/editGenre/${genres.id}" class="link">Изменить</a>
                <a href="/deleteGenre/${genres.id}" class="link">Удалить</a>
            </td>
        </tr>
    </c:forEach>
</table>
<h2 class="headline">Добавить новый жанр</h2>
<c:url value="/addGenre" var="genre"/>
<a href="${genre}" class="link">Добавить</a>
</body>
</html>

Actually framework is treating request as post only and it is creating a new row instead of updating. 实际上,框架将请求仅视为发布,并且它正在创建新行而不是进行更新。

HTML forms do not support PUT, PATCH or DELETE actions. HTML表单不支持PUT,PATCH或DELETE操作。 So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. 因此,在定义从HTML表单调用的PUT,PATCH或DELETE路由时,您将需要向表单添加一个隐藏的_method字段。 The value sent with the _method field will be used as the HTTP request method: 与_method字段一起发送的值将用作HTTP请求方法:

So override post with put like below. 因此,使用如下所示的内容覆盖帖子。

<form method="post" ...>
  <input type="hidden" name="_method" value="put" />
...

谢谢大家的帮助,解决方案是添加一个设置ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM