没有冗余代码的Spring MVC更新?

时间:2013-12-16 20:17:59

标签: spring-mvc crud spring-form

我正在使用Spring MVC控制器和视图来实现名为Partner的简单对象的CRUD操作。更新操作让我烦恼。看起来我需要手动编写几行代码,我希望Spring MVC会自动处理。我在这里缺少最佳实践吗?

以下是我的观点:

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

这是我的更新操作的控制器方法:

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

困扰我的代码行是:

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

我是否真的需要在数据库中查找现有的合作伙伴并明确更新该对象的每个字段?我已经有一个具有所有正确值的Partner对象。有没有办法将该对象直接存储到数据库中?

我已经查看了Spring MVC CRUD controller best pactice,但这并没有完全回答我的问题。

2 个答案:

答案 0 :(得分:1)

作为一个可能的建议,您可以查找现有的Partner对象作为模型创建的一部分,以便此模型实例支持表单,Spring将字段直接绑定到它。实现此目的的一种方法是在控制器中创建一个负责创建模型的显式方法。

例如:

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

然后你可以从updatePartner方法中删除复制 - 因为Spring已经将表单字段直接绑定到加载的Partner对象。

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

有一点需要注意 - 因为每次向控制器发出请求都会调用createModel方法(而不只是updatePartner),所有请求中都需要partnerId路径变量。

有一篇帖子here可以解决该问题。

答案 1 :(得分:0)

您可以使用merge更新所需的值,例如:

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

此外,我建议您使用@Transactional@Repository以及{{1}}

使用DAO Pattern和Spring交易支持