有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我将ID作为参数传递给编辑页面,它就会出现。在表单中,我进行了更改,当我提交时,POST将创建一个新对象,而不是我使用传递的ID编辑的对象

我已经花了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.

课程类型:

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);
    }
}

服务:

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;
    }
}

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转换页面:

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

共 (1) 个答案

  1. # 1 楼答案

    实际上,该框架将请求视为post only,并创建一个新行,而不是更新

    HTML表单不支持放置、修补或删除操作。因此,在定义从HTML表单调用的PUT、PATCH或DELETE路由时,需要在表单中添加一个隐藏的_方法字段。与_method字段一起发送的值将用作HTTP请求方法:

    所以用下面这样的方式覆盖帖子

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