简体   繁体   中英

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.

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.

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:

<%@ 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:

<%@ 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. 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. The value sent with the _method field will be used as the HTTP request method:

So override post with put like below.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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