【问题标题】:Why is my change not flushed to the database at the end of the servlet call?为什么在 servlet 调用结束时我的更改没有刷新到数据库中?
【发布时间】:2014-01-06 14:49:36
【问题描述】:

我对 JTA 事务范围如何与 servlet 调用交互感到困惑。假设我有下面的 servlet:

@WebServlet("/UpdateFooServlet")
public class UpdateFooServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@Inject
private FooDAO fooDAO;

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    Foo foo = fooDAO.findById(Integer.parseInt(request.getParameter("id")));
    foo.setName(request.getParameter("name"));  
            // Should the transaction flush/commit after this returns?
}
}

FooDAO 被注解为@Stateless,并且有一个使用@PersistenceContext 注入的EntityManager。 findById 只是调用 em.find 并返回匹配的 Foo。当我发布到 servlet 时,对 foo 对象的更新不会持久化到数据库中。

这是部署在 JBoss AS7 服务器上,使用内存中的 H2 数据库。我可以毫无问题地将 Foo 对象持久保存到数据库中,但更新令人困惑。我无法显式刷新实体管理器(即使我将 EntityManager 注入到 servlet 中,我也无法加入事务)。如果我两次 POST 到 servlet,我可以在控制台中看到更新 SQL,但如果我调用 servlet 一次则看不到。

【问题讨论】:

    标签: hibernate jpa transactions jboss7.x jta


    【解决方案1】:

    问题在于事务边界是在 EJB 层上定义的,而不是在 Servlet 上,这意味着如果您在 EJB 方法中执行此操作,那么在您的 EJB 方法返回后将提交到 DB。还要记住,您的 servlet 中的 Foo 实例不再受管理,这意味着不再跟踪其更改。

    另一方面,在您的 servlet 中实现任何数据库操作/业务逻辑都是一种不好的做法。

    为了让它更短:使用以下代码在您的 DAO 服务中创建另一个方法 save(Fao fao)

    em.merge(fao);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-08
      • 2012-02-05
      • 1970-01-01
      • 2020-10-12
      • 2020-05-02
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多