最佳实践从JSP获得EntityManger和UserTransaction的(Best pract

2019-07-30 18:31发布

目前我正在试图找出让一个实体管理器,并在我的应用程序一个UserTransaction的最佳途径。

在JBoss的5.1我能直接注射到JSP文件中,但这不再允许:

<%!@PersistenceContext(unitName = "unitname")
    public EntityManager em;

    @Resource
    UserTransaction utx;
%>

我访问emutx在我的应用程序,如Servlet和控制器类不同的位置。 因此,这将是巨大的,有它在一个地方,并在全球范围内访问它,但我也没弄明白怎么还没有做到这一点。 任何暗示将不胜感激。

Answer 1:

我发现了如何获得的EntityManager和UserTransaction的Servlet中,控制器类和JSP文件。

让我们先从SessionBeans。 我重新定义了我所有的控制器类为无状态SessionBeans。 会话Bean允许的ressource注射。 这是我做的:

@Stateless
public class UserHandling {
  @PersistenceContext(unitName = "SSIS2")
  private static EntityManager em;

  @Resource
  private UserTransaction utx;

  public User getUser(int userId) {
    User userObject = em.find(User.class, userId);
    return userObject;
  }
}

如果需要在会话bean类另一个会话Bean,它可以与被注入@EJB注释:

@Stateless
public class UserHandling {
  @PersistenceContext(unitName = "SSIS2")
  private static EntityManager em;

  @Resource
  private UserTransaction utx;

  @EJB
  UserHandling uh; RoleHandling rh; 

  public User getUser(int userId) {
    User userObject = em.find(User.class, userId);
    return userObject;
  }
}

在JSP文件中,可以通过查找该InitialContext的获取会话Bean控制器类:

<%
    InitialContext ic = new InitialContext();
    UserHandling uh = (UserHandling) ic.lookup("java:app/" + application.getContextPath() + "/UserHandling");
%>


Answer 2:

该问题正在解决

因为他们在多个线程共享Servlet和JSP必须是无状态的。 一个EntityManager不保持状态,所以单个实例不能并发线程共享。

我们希望获得一个EntityManager,优选由Servlet容器管理的平滑/无缝机制。

Servlet的容器​​管理的持久化上下文

让我们引入ContainerManagedPersistenceContext到servlet / JSP运行。

我们将在稍后定义它。 让我们先来看看它如何被用来注入一个EntityManagerJSP

<%! @Inject
    @ContainerManagedPersistenceContext.Qualifier
    public EntityManager em;
%>

或者,更好的是到控制器(因为我们不希望将数据恢复/业务逻辑从我们的JSP分开,对吧?):

@Named
@SessionScoped
public class SessionController implements Serializable
{
    ...

    @Inject
    @ContainerManagedPersistenceContext.Qualifier
    private EntityManager em;
}

但我不(还)有CDI提供

如果你没有CDI,但你有JSF,那么上下文可以注射作为一种老式的标准JSF @ManagedProperty

@Named
@SessionScoped
public class SessionController implements Serializable
{
    ...

    @ManagedProperty(value = "#{containerManagedPersistenceContext}")
    ContainerManagedPersistenceContext cmpContext;

    ...
    public void myMethod() {
        EntityManager em = cmpContext.getEntityManager();
       try {
            ...
        } finally {
            em.close();
        }
    }
}

请记住, -所有我们不得不去这种努力首先由于同样的原因-该EntityManager绝缓存/任何地方保存。

交易

使用EntityTransaction由提供EntityManager的开始/提交/回滚:

EntityTransaction交易= em.getTransaction();

ContainerManagedPersistenceContext

这被定义为应用程序作用域控制器和PersistenceContext

@PersistenceContext(name = ContainerManagedPersistenceContext.NAME,
                    unitName = ContainerManagedPersistenceContext.UNIT_NAME)
@ApplicationScoped
public class ContainerManagedPersistenceContext implements Serializable
{
    private static final long serialVersionUID = 1L;

    // UNITNAME must match persistence.xml: <persistence-unit name="myUnitName">
    public static final String UNITNAME = "myUnitName";
    public static final String NAME = "persistence/" + UNIT_NAME;


    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD, ElementType.FIELD,
             ElementType.PARAMETER, ElementType.TYPE})
    public static @interface Qualifier { }

    // Servlets must be stateless (shared across multiple threads).
    // EntityManager is not stateless (cannot be shared across threads).
    // Obtain Container Managed EntityManager - and do NOT cache.
    @Produces @Qualifier
    public static EntityManager getEntityManager() throws NamingException
    {
        EntityManager lookup = InitialContext.doLookup("java:comp/env/" + NAME);
        return lookup;
    }
}

限制

由于写的,这限定了用于Servlet容器一个特别命名PersistenceContext。 由于unitName没有参数,它不提供的灵活性水平:

@PersistenceContext(unitName = "unitname")
public EntityManager em;

备择方案

定义你的Servlet的一个PersistenceContext,并使用JNDI名称查找 。



Answer 3:

嗯,我想你应该从不同的角度看这个问题? 为什么你需要调用EJBJSP页面?

JSP页面不应该包含的代码,它仅用于演示。 我建议你添加ServletJSF framework ,让ServletManagedBean调用EJB ,然后将参数传递给JSP

希望它可以帮助你



Answer 4:

您可以使用下面的代码片段通过JNDI查找检索的EntityManager和/或UserTransaction的:

try {
   Context ic = (Context) new InitialContext();
   EntityManager em = (EntityManager) ic.lookup("java:comp/env/*<persistence-context-name>*");
   UserTransaction ut = (UserTransaction) ic.lookup("java:comp/env/UserTransaction");
} catch (NamingException ne) {...}


文章来源: Best practice to get EntityManger and UserTransaction from JSP