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.
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.
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;
}
}
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);
}
}
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);
}
}
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;
}
}
<%@ 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>
<%@ 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.