如何在Spring MVC中的页面提交上绑定Object属性?

时间:2014-05-26 21:21:42

标签: java spring hibernate spring-mvc

在阅读了教程和文档之后,我仍然不理解在 SpringMVC + hibernate 中绑定某些Object属性的机制。

假设我们有一个班级Poem

package com.test.poems.model;

import com.tastyminerals.poems.model.Author;
import com.tastyminerals.poems.model.Genre;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;


@Entity
@Table(name = "P_POEM")
public class Poem {

    @Id
    @GeneratedValue
    @Column(name="ID")
    private Integer id;

    @Column(name="TITLE")
    private String title;

    @Column(name="BODY")
    private String body;

    @Column(name="DATE")
    private String date;


    @ManyToOne
    @JoinColumn(name="ID", referencedColumnName="ID_AUTHOR", insertable = false, updatable = false)
    private Author author;

    @ManyToOne
    @JoinColumn(name="ID", referencedColumnName="ID_GENRE", insertable = false, updatable = false)
    private Genre genre;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Author getAuthor() {
        return author;
    }

    public Genre getGenre() {
        return genre;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }

    public void setGenre(Genre genre) {
        this.genre = genre;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

}

和一个班级Author

@Entity
@Table(name = "AUTHORS")
public class Author {

    @Id
    @GeneratedValue
    @Column(name="ID_AUTHOR")
    private Integer id;

    @Column(name="NAME")
    private String name;

/* getters and setters */

我需要通过hibernate将我的诗提交到mysql数据库。为此,我创建了一个简单的jsp页面,其中包含所有Poem属性的输入字段。 提交后RequestMethod.POST会返回titlebody和作者name的字符串值。

但是,这会产生类似于:Failed to convert property value of type 'java.lang.String' to required type 'com.test.model.Author' for property 'author'的类型转换错误。

Poem类期望将Author对象设置到其中,但改为使用String name。我想知道为什么Spring没有进行必要的转换,因为我在控制器方法中明确地创建了Author?页面提交后是否应自动解析并设置其值?

@RequestMapping(value = "/poem/add", method = RequestMethod.GET)
    public ModelAndView addPoemPage() {
        ModelAndView modelAndView = new ModelAndView("poem-add");
        modelAndView.addObject("author", new Author());
        modelAndView.addObject("poem", new Poem());
        return modelAndView;
    }

    @RequestMapping(value = "/poem/add", method = RequestMethod.POST)
    public ModelAndView addingPoem(@ModelAttribute Poem poem,
            @ModelAttribute Author author) {

        ModelAndView modelAndView = new ModelAndView("home");
        authorService.addAuthor(author);

        poem.setAuthor(author);
        poemService.addPoem(poem);
        return modelAndView;
    }

我的jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<c:set var="url">${pageContext.request.requestURL}</c:set>
<link
    href="${pageContext.request.contextPath}/resources/css/poem-add.css"
    rel="stylesheet" />
<title>Writing a poem</title>
</head>
<body>
    <h1>New poem</h1>
    <p>Here you can write your poem.</p>
    <form:form method="POST" commandName="poem"
        action="${pageContext.request.contextPath}/poem/add.html">
        <table>
            <tbody>
                <tr>
                    <td>Title:</td>
                    <td><input id="" title="Your poem's title" id="title"
                        name="title" type="text" class="input" /></td>
                </tr>
                <tr>
                    <td>Author:</td>
                    <td><input title="Author's name" id="author" name="author"
                        type="text" class="input" /></td>
                </tr>
                <tr>
                    <td>Date:</td>
                    <td><input title="Date of creation" id="date" name="date"
                        type="text" class="input" /></td>
                </tr>
                <tr>
                    <td>Text:</td>
                    <td><textarea title="Your poem goes here" rows="15" cols="50"
                            class="input"> </textarea></td>
                </tr>
            </tbody>
        </table>
        <table class="actions">
            <tr>
                <td><a
                    href="${pageContext.request.contextPath}/collection.html"><input
                        type="button" value="Back" class="button" /></a></td>
                <td><a
                    href="${pageContext.request.contextPath}/collection.html"><input
                        type="submit" value="Submit" class="button" /></a></td>
            </tr>
        </table>
    </form:form>
</body>
</html>

我知道我需要PropertyEditorBeanWrapper。但我根本不明白我在哪里以及如何实施它们?有什么区别?

总结我的问题,我需要解释正在发生的事情&#34;幕后花絮&#34;在我点击提交按钮后,在hibernate和SpringMVC之间。如果您能为我的案例提供PropertyEditorBeanWrapper的样本,我将无休止地感激不尽。

1 个答案:

答案 0 :(得分:2)

  

我需要解释之间“幕后”的内容   hibernate和SpringMVC

:还没有休眠。您只需使用Spring MVC将普通bean(模型)映射到JSP。

  

我知道我需要一个PropertyEditor或BeanWrapper。

:您现阶段不需要PropertyEditor。 PropertyEditor用于高级类型转换,例如当您希望将传入日期字符串“dd-mm-yyyy Zone”转换为java.util.Date对象时,反之亦然。

  

我想知道为什么Spring没有必要   转换,因为我在我的控制器方法中明确地创建了作者?   不应该在页面后自动解析和设置其值   提交?

:如果使用Spring Form标记将JSP字段正确映射到model属性,Spring将自动解析。在您的情况下,JSP表单字段未正确映射到模型,它应如下所示

<form:form method="POST" modelAttribute="poem"
    action="${pageContext.request.contextPath}/poem/add.html">
    <table>
        <tbody>
            <tr>
                <td>Title:</td>
                <td><form:input path="poem.title" title="Your poem's title" 
                    type="text" class="input" /></td>
            </tr>
            <tr>
                <td>Author:</td>
                <td><form:input path="poem.author.name" title="Author's name"
                    type="text" class="input" /></td>
            </tr>
            <tr>
                <td>Text:</td>
                <td><form:textarea path="poem.body" title="Your poem goes here" rows="15" cols="50"
                        class="input" /></td>
            </tr>
        </tbody>
    </table>
    <table class="actions">
        <tr>
            <td><a
                href="${pageContext.request.contextPath}/collection.html"><input
                    type="button" value="Back" class="button" /></a></td>
            <td><a
                href="${pageContext.request.contextPath}/collection.html"><input
                    type="submit" value="Submit" class="button" /></a></td>
        </tr>
    </table>
</form:form>

您可以向模型添加许多属性,但只能将一个模型属性附加到<form>而不是两个。你的控制器看起来像这样。

@RequestMapping(value = "/poem/add", method = RequestMethod.GET)
    public ModelAndView addPoemPage() {
        ModelAndView modelAndView = new ModelAndView("poem-add");
        Author author = new Author();
        Poem poem = new Poem();
        poem.setAuthor(author); 
        modelAndView.addObject("poem", new Poem());
        return modelAndView;
    }

    @RequestMapping(value = "/poem/add", method = RequestMethod.POST)
    public ModelAndView addingPoem(@ModelAttribute("poem") Poem poem) {

        ModelAndView modelAndView = new ModelAndView("home");
        authorService.addAuthor(poem.getAuthor);
        poemService.addPoem(poem);
        return modelAndView;
    }