【发布时间】:2015-04-08 10:41:19
【问题描述】:
我想做什么:
我刚开始使用 JPA,因此我想从不同的角度了解持久实体是如何工作的(应用程序管理的、容器管理的)。应用程序管理工作正常,但是我在使用 TestServlet 从 Web 应用程序中通过实体管理器持久化实体时遇到问题。
到目前为止我做了什么:
IDE:NetBeans 8.0.2 服务器:GlassFish 4.1 mysql 5.6 JPA 2.1:EclipseLink
- 我创建了一个 Web 应用程序项目。
- 我已经使用 NetBeans 向导从数据库中导入了实体。 由于某种原因,我无法从 jdbc/__default 导入它们。 我必须创建一个新的数据源。在这种情况下,它是 jdbc/__onlineshop
我只是想在 Servlet 中创建一个实体并将其保存在数据库中,以便在继续之前了解它是如何工作的,但显然我不太明白。
我已连接到数据库,我可以通过 Java 应用程序访问它,但不能使用 Web 容器中的 Servlet。
MySQL 驱动程序位于类路径 MAIN - Libraries 中。
不抛出异常。 Servlet 被调用,我可以在浏览器中看到它。但是通过 RequestDispatcher 的重定向也不起作用,浏览器 URL 停留在 web-jpa/test。
我的问题:
由于持久化不起作用,我的 Servlet 或 persistence.xml 有什么问题吗?
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/ persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="jpa-webPU" transaction-type="JTA">
<jta-data-source>jdbc/__onlineshop</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
TestServlet.java:
package jpa;
import java.io.IOException;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.UserTransaction;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@PersistenceUnit
EntityManagerFactory emf;
@Resource
private UserTransaction ut;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
EntityManager em = emf.createEntityManager();
Customer customer = new Customer();
customer.setEmail("email@test.com");
customer.setPassword("password");
try
{
ut.begin();
em.persist(customer);
ut.commit();
} catch (Exception e) {
try
{
ut.rollback();
} catch (Exception e1)
{
e1.printStackTrace();
}
throw new ServletException(e.getMessage());
}finally
{
em.close();
}
RequestDispatcher dispatcher = request.getRequestDispatcher ("index.html");
dispatcher.forward(request, response);
}
}
谢谢!
p.s.:感谢任何提示!
【问题讨论】:
-
您混淆了重定向和转发。转发只是将处理请求的责任转移给另一个组件。它不能更改 URL。重定向(使用 HttpServletResponse.sendRedirect())向浏览器发送响应并告诉它转到另一个 URL。这可以改变 URL。
-
你有什么问题?
-
我已经编辑了帖子。基本问题是:我在 servlet 中持久化实体的方式有什么问题吗?我不明白为什么它不将实体保留在数据库中。
-
如果它没有抛出任何异常,那么你的实体可能已经被持久化了。确保查看正确的数据库。也就是说,您不应该使用 servlet 中的 EM。委托给事务性 CDI bean 或无状态 EJB。使用声明式事务管理而不是那些可怕的 try/catch/commit/rollback 块。
-
请转移到 EJB。这样,您无需手动获取实体管理器,也无需手动处理丑陋的用户事务和手动回滚。您所需要的只是 EJB 方法中的
em.persist(entity);行。只需创建一个类,注释它@Stateless,添加一个@PersistenceContext private EntityManager em;字段并添加处理它的公共方法。最后通过@Inject将它注入到servlet 中,并让它依次调用一个这样的EJB 方法。就这样。单个无状态 EJB 方法调用透明地算作单个完整事务,包括回滚等等。
标签: jakarta-ee servlets jpa persistence entitymanager