在Spring MVC中将子类属性映射到表单路径

3

产品

@Entity
@Table(name = "product")
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public class Product {
    @Id
    @Column(name = "id")
    @GeneratedValue()
    private Integer id;
@Column(name = "shortDescription")
    private String shortDescription;

书籍

@Entity
@DiscriminatorValue(value = "Book")
public class Book extends Product {
    @Column(name = "isbn")
    private String isbn;    

控制器

@RequestMapping(value="/product/add",
            method = RequestMethod.POST)
    public String addProduct(@ModelAttribute("product")
         Product product, BindingResult result
            ){
         if(null == product.getId()){
             productService.addProduct(product);
         }else{
             productService.updateProduct(product);
         }
                return "redirect:/";
                }

我正在尝试在jsp中显示此属性。

    <head>
    <title>Products - Acme Web Store</title>
    <script type="text/javascript">
    function deleteProduct(productId){
        if(confirm('Do you want to delete this product ?')){
            var url = 'delete/'+productId;
            window.location.href = url;
        }
    }
    </script>
</head>
<body>    
        <h2>Product Store - Acme Web Store</h2>
        <p style="color: green; font-weight: bold;">
        To add a new product please click <a href="<c:url var="action" value="/product/add"></c:url>"> <img
            src="<c:url value='/images/vcard_add.png' />"
            title="Add a New Product" />
        </a>
    </p>
    <c:url var="action" value="/product/add"></c:url>
    <form:form method="post" action="${action}" commandName="product"
        cssClass="productForm">
        <table>
            <c:if test="${!empty product.title}">
                <tr>
                    <td><form:label path="id" cssClass="productLabel">
                            <spring:message code="label.productId" />
                        </form:label></td>
                    <td><form:input path="id" readonly="true" size="8"
                            disabled="true" /> <form:hidden path="id" /></td>
                </tr>
            </c:if>
            <tr>
                <td><form:label path="title" cssClass="productLabel">
                        <spring:message code="label.productTitle" />
                    </form:label></td>
                <td><form:input path="title" /></td>
            </tr>
            <tr>
                <td><form:label path="shortDescription" cssClass="productLabel">
                        <spring:message code="label.shortDescription" />
                    </form:label></td>
                <td><form:input path="shortDescription" /></td>
            </tr>
                <tr>
                    <td><form:label path="isbn" cssClass="productLabel">
                            <spring:message code="label.isbn" />
                        </form:label></td>
                    <td><form:input path="isbn" /></td>
                </tr>
                <tr>
                    <td><form:label path="format" cssClass="productLabel">
                            <spring:message code="label.format" />
                        </form:label></td>
                    <td><form:input path="format" /></td>
                </tr>
            <tr>
                <td colspan="2"><c:if test="${!empty product.productName}">
                        <input type="submit"
                            value="<spring:message code="label.editproduct"/>" />
                    </c:if> <c:if test="${empty product.productName}">
                        <input type="submit"
                            value="<spring:message code="label.addproduct"/>" />
                    </c:if></td>
            </tr>
            <tr>
                <td><form:label path="type" cssClass="productLabel">
                        <spring:message code="label.type" />
                    </form:label></td>
                <td>
                <form:select path="type">
                        <form:option value="0" label="Select One" />
                        <form:option value="1" label="Book" />
                        <form:option value="2" label="Game" />
                </form:select>
                </td>
            </tr>
        </table>
    </form:form>


    <h3>List of products in Library</h3>
    <c:if test="${!empty productList}">
        <table class="productTable">
            <tr>
                <th width="160">Product Title</th>
                <th width="190">Product Short Description</th>
                <th width="80">Product ISBN</th>
                <th width="80">Product Format</th>
                <th width="60">Action</th>
            </tr>
            <c:forEach items="${productList}" var="product">
                <tr>
                    <td><a href="<c:url value='/edit/${product.id}' />">${product.productName}</a>
                    </td>
                    <td>${product.title}</td>
                    <td>${product.shortDescription}</td>
                    <td>${product.isbn}</td>
                    <td>${product.format}</td>
                    <td><img src="<c:url value='/images/vcard_delete.png' />"
                        title="Delete product"
                        onclick="javascript:deleteproduct(${product.id})" /> <a
                        href="<c:url value='/edit/${product.id}' />"> <img
                            src="<c:url value='/images/vcard_add.png' />"
                            title="Edit product" />
                    </a></td>
                </tr>
            </c:forEach>
        </table>
    </c:if>


</body>
</html>

我遇到了这个错误:invalid property 'isbn' of bean class [com.mycompany.app.model.Product]: Bean property 'isbn' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter? 我知道我的做法不对,一定有一种方法可以将Product转换成Book,这样我就可以获取ISBN属性。怎么做?

让我们看看你的<form:form>绑定和你所拥有的getter/setter。 - Sotirios Delimanolis
我在这里发布的jjsp片段位于form:form标签内部。 - ThaSaleni
发布整个JSP。 - ThaSaleni
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/45667/discussion-between-thasaleni-and-sotirios-delimanolis - ThaSaleni
是的,刚刚添加了控制器片段。 - ThaSaleni
显示剩余4条评论
1个回答

2

只需要更改

@ModelAttribute("product") Product product

为了

@ModelAttribute("product") Book product

当Spring看到类型为Product时,它会创建一个Product对象,而不是一个Book对象。显然,Product没有名为isbn的属性,因此您不能期望它解析该属性的<form:input>
您可能需要澄清您要做什么。当您期望子类型时,不能使用超类型。

事实上,我可以拥有各种类型的产品(即继承自Product的物品),我不想为每个产品单独创建一个页面...我希望能够添加任何类型的产品,无论是书籍、DVD还是游戏,并显示其独特属性。 - ThaSaleni
@ThaSaleni,我想不出你如何使用继承来实现这个功能。我认为最好还是使用不同的页面。 - Sotirios Delimanolis
@ThaSaleni 如果您不想为每个产品类型创建不同的页面,那么您应该手动进行每个可用产品类型的对象组装。 - Bart
你能举个例子来说明你所说的吗?@Bart - ThaSaleni
这并不难。只需检测产品类型并创建一个映射器类,将请求中的所有相关属性映射到指定的产品即可。 - Bart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接