0

我正在开发一个 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,但这并没有完全回答我的问题。

4

2 回答 2

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路径变量需要存在于所有请求中。

这里有一篇文章讨论了该问题的解决方案。

于 2013-12-17T13:48:19.770 回答
0

您可以使用合并来更新所需的值,例如:

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

另外,我建议您将DAO 模式和 Spring 事务支持与@Transactional和一起使用@Repository

于 2013-12-17T16:37:28.900 回答