I'm working on a Spring MVC controller and views to implement CRUD operations for a simple object named Partner. The update operation troubles me. It seems like I need to write several lines of code manually that I expected Spring MVC would take care of automatically. Is there a best practice that I'm missing here?

Here's my view:

<%@ include file="include.jsp"%>

<form:form commandName="partner">
    <input type="hidden" name="_method" value="PUT" />
    <table>
        <tr>
            <td>Id:</td>
            <td><form:input path="id" disabled="true" /></td>
        </tr>
        <tr>
            <td>Name:</td>
            <td><form:input path="name" /></td>
        </tr>
        <tr>
            <td>Logo:</td>
            <td><form:input path="logo" /></td>
        </tr>
        <tr>
            <td>On-screen text:</td>
            <td><form:textarea path="onScreenText" /></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Save Changes" /></td>
        </tr>
    </table>
    </form:form>

And here's my controller method for the update operation:

@RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(@ModelAttribute Partner partner, @PathVariable int partnerId) {
    EntityManager entityManager = DatabaseHelper.getEntityManager();
    try {
        Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
        entityManager.getTransaction().begin();
        partnerToUpdate.setId(partnerId);
        partnerToUpdate.setName(partner.getName());
        partnerToUpdate.setLogo(partner.getLogo());
        partnerToUpdate.setOnScreenText(partner.getOnScreenText());
        entityManager.persist(partnerToUpdate);
        entityManager.getTransaction().commit();
    }
    finally {
        entityManager.close();
    }
    return new ModelAndView("redirect:/partner");
}

The lines of code that trouble me are:

Partner partnerToUpdate = entityManager.find(Partner.class, partnerId);
partnerToUpdate.setId(partnerId);
partnerToUpdate.setName(partner.getName());
partnerToUpdate.setLogo(partner.getLogo());
partnerToUpdate.setOnScreenText(partner.getOnScreenText());

Do I really need to look up the existing Partner in the database and explicitly update each field of that object? I already have a Partner object with all the right values. Is there no way to store that object directly to the database?

I've already looked at Spring MVC CRUD controller best pactice, but that didn't quite answer my question.

有帮助吗?

解决方案 2

You can use merge to update the desired values, something like:

    @RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
    public ModelAndView updatePartner(@ModelAttribute Partner partner, @PathVariable int partnerId) {
        EntityManager entityManager = DatabaseHelper.getEntityManager();
        try {
            entityManager.getTransaction().begin();
            partner.setId(partnerId);
            entityManager.merge(partner);
            entityManager.getTransaction().commit();
        }
        finally {
            entityManager.close();
        }
        return new ModelAndView("redirect:/partner");
    }

Also, I recommend You to use the DAO Pattern and Spring Transaction Support with @Transactional and @Repository

其他提示

As one possible suggestion, you could lookup the existing Partner object as part of model creation so that this model instance backs the form and Spring binds the fields directly to it. One way to achieve this would be to create an explicit method in the controller responsible for creating the model.

For example:

@ModelAttribute("partner")
public Partner createModel(@PathVariable int partnerId) {
    Partner partner = entityManager.find(Partner.class, partnerId);
    return partner;
}

And then you could remove the copying from the updatePartner method - because Spring will already have bound the form fields directly to the loaded Partner object.

@RequestMapping(value="/partner/{partnerId}", method=RequestMethod.PUT)
public ModelAndView updatePartner(@ModelAttribute("partner") Partner partner) {
    EntityManager entityManager = DatabaseHelper.getEntityManager();
    try {
        entityManager.getTransaction().begin();
        entityManager.persist(partner);
        entityManager.getTransaction().commit();
    }
    finally {
        entityManager.close();
    }
    return new ModelAndView("redirect:/partner");
}

One caveat - because the createModel method would get called for every request to the controller (not just updatePartner), the partnerId path variable would need to be present in all requests.

There's a post here which goes over a solution to that issue.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top