【问题标题】:How to get a static instance of entityManager in broadleaf?如何在阔叶树中获取 entityManager 的静态实例?
【发布时间】:2017-10-11 23:14:59
【问题描述】:

此问题专门针对阔叶贸易。 我必须以静态方法加载实体。由于注入 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;

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

【问题讨论】:

标签: java hibernate jpa broadleaf-commerce


【解决方案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);
}

【讨论】:

    【解决方案2】:

    要明确的是,在企业容器内通过Peristence.createEntityManagerFactory 获取EntityManagerFactory 是个坏主意,请改用容器功能。如果您在容器外需要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 标记为间谍对象,并在 @Before 测试方法中对其进行初始化,然后在测试类上调用 initMocks 即可。 最后但并非最不重要的一点是不要忘记创建和提交事务,因为你没有容器来为你做这件事。

    【讨论】:

      【解决方案3】:

      一个 Broadleaf 特定的答案(如果你需要一个 blPU EntityManager)是使用:

      GenericEntityDaoImpl.getGenericEntityDao().getEntityManager();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-27
        • 1970-01-01
        相关资源
        最近更新 更多