如何在broadleaf中获取entityManager的静态实例?

时间:2016-06-12 06:56:24

标签: java hibernate jpa broadleaf-commerce

这个问题是针对阔叶商业的。 我必须在静态方法中加载实体。由于注入entityManager没有帮助(因为我无法在静态方法中访问它),我无法加载实体。

我尝试使用Persistence.createEntityManagerFactory,但它没有帮助。 这是我的示例代码。

Query query = Persistence.createEntityManagerFactory("blPU").createEntityManager().createQuery("some query");
List results = query.getResultList();

我得到的错误: -

javax.persistence.PersistenceException: No Persistence provider for EntityManager named blPU

对于我必须在实例方法中使用它的情况,entityManager就像一个魅力:

@PersistenceContext(unitName="blPU")
protected EntityManager em;

所以我想这不是任何类路径问题。 任何帮助都会很棒。

3 个答案:

答案 0 :(得分:1)

如果您实际上不需要在静态上下文中编写查询但仍希望以静态方法访问实体,我将建议您通过CDI上下文查找EJB的现有实例使用以下通用代码:

public class Util {
    private static <T> T lookUpClassInBeanManager(Class<T> clazz) {
        BeanManager bm = CDI.current().getBeanManager();
        Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
        CreationalContext<T> ctx = bm.createCreationalContext(bean);
        return (T) bm.getReference(bean, clazz, ctx);
    }

    public static YourDaoClass lookUpYourDaoClass() {
        return lookUpClassInBeanManager(YourDaoClass.class);
    }
}

你的DaoClass看起来像那样:

@Stateless
public class YourDaoClass {

    @PersistenceContext(unitName = "blPU", type = PersistenceContextType.TRANSACTION)
    protected EntityManager em;

    public <T> List<T> getEntityListByType(Class<T> clazz) {
        TypedQuery<T> query = em.createQuery("select entity from "+ clazz.getSimpleName() +" entity", clazz);
        return query.getResultList();
    }
}

在静态方法中,可以这样使用:

public static void tryEJBinStaticContext() {
    YourDaoClass dao = Util.lookUpYourDaoClass();
    List<SomeEntity> list = dao.getEntityListByType(SomeEntity.class);
}

答案 1 :(得分:0)

要明确将EntityManagerFactory放在企业容器内的Peristence.createEntityManagerFactory上是个坏主意,请改用容器功能。如果您需要在容器外部Peristence.createEntityManagerFactory,请仅供测试或出于其他原因。你必须创建Java SE JPA上下文,我创建了这个example project来解释如何为JPA测试做这件事。

如果你计划自己做的话,这里有一些项目通知可以更好地理解。

最重要的部分是只创建一个persistence.xml,避免为测试创建另一个,而是覆盖persistence.xml的设置。这对你来说应该足够了persistence.xml:

<persistence-unit name="application-ds" transaction-type="JTA">
    <jta-data-source>java:/youApplication</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>

在示例项目中,我添加了一些用于生成数据库的属性,但这不是必需的,也许你有另一种方法来为数据库做准备。

要创建EntityManagerFactory,请将持久性单元名称(这很重要)与属性映射一起传递给Persistence.createEntityManagerFactory。通过此步骤进行设置 java se的持久性提供程序。它存在一些限制,首先我们没有任何JTA和JPA无法自动发现实体类。 这里是最重要的属性:

properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
properties.put("javax.persistence.provider", "org.hibernate.jpa.HibernatePersistenceProvider");
properties.put("javax.persistence.jtaDataSource", null);
properties.put("hibernate.archive.autodetection", "class");

下一个技巧是如何将注入或持久性提供程序引入ejb,而mockito就是解决方案。代码优先:

@InjectMocks
private UserDao dao;

@Spy
private EntityManager em;

@Before
public void prepare() {
    em = JpaProvider.instance().getEntityManager();
    initMocks(this);
}

说明:Mockito用于将实体管理器注入ejb。将EntityManager标记为spied对象,并在@Before测试方法中初始化它,然后在测试类上调用initMocks即可。 最后但并非最不重要的是不要忘记创建和提交事务,因为你没有容器来为你做。

答案 2 :(得分:0)

Broadleaf特定答案(如果您需要blPU EntityManager)将使用:

GenericEntityDaoImpl.getGenericEntityDao().getEntityManager();