简体   繁体   中英

Mapping a subclass property to form path in Spring MVC

Product

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

Book

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

Controller

@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, where I'm trying to display this property

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

I get this error: 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?

I know I'm not doing this right, there must be a way to cast Product to Book so I can get the ISBN property, how do we do this?

Just change

@ModelAttribute("product") Product product

to

@ModelAttribute("product") Book product

When Spring sees the type Product , it will create a Product object, not a Book object. Obviously, Product does not have a property named isbn , so you cannot expect it to resolve a <form:input> for that property.

You might want to clarify what you are trying to do. You can't use super types when you are expecting sub types.

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