java - 如何让EntityManager在DAO Factory中正常工作?

标签 java jpa eclipselink dao openejb

我想实现描述的 DAO 模式 here与 EclipseLink 和 OpenEJB。第一次尝试链接中列出的图 9.1 效果很好。代码如下:

// CustomerDAO
@Local
public interface CustomerDAO {
    Customer findCustomer(String id);
}

// OracleCustomerDAO
@Stateless
@Local(CustomerDAO.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class OracleCustomerDAO implements CustomerDAO {

    @PersistenceContext(unitName = "MY_EJB")
    private EntityManager em;

    public Customer findCustomer(String id) {
        return em.find(Customer.class, id);
    }
}

为我服务:

public class CustomerService implements CustomerServiceLocal {
    @EJB
    CustomerDAO customerDAO;

    public Customer findCustomer(String id) {
        return customerDAO.findCustomer(id);
    }
}

但是,当我想要适应工厂模式时,我不知道什么是正确的方法。我将代码编写为链接中的教程,并添加了两个类,如下所示:

// DAOFactory
public abstract class DAOFactory {
    public abstract CustomerDAO getCustomerDAO();

    public enum Factory {
        ORACLE;
    }

    public static DAOFactory getDaoFactory(Factory whichFactory) {
        switch (whichFactory) {
        case ORACLE:
            return new OracleDAOFactory();
            break;
        default:
            break;
        }
    }
}

// OracleDAOFactory
public class OracleDAOFactory extends DAOFactory {

    @Override
    public CustomerDAO getCustomerDAO() {
        return new OracleCustomerDAO();
    }

}

我将我的服务修改为:

public class CustomerService implements CustomerServiceLocal {

    public Customer findCustomer(String id) {

        CustomerDAO customerDAO = DAOFactory.getDaoFactory(Factory.ORACLE).getCustomerDAO();

        return customerDAO.findCustomer(id);
    }
}

这给了我一个NullPointerException。当我使用调试器跟踪代码时,我发现OracleCustomerDAO中的EntityManagernull。我认为这是因为我没有在新服务中进行任何 @EJB 注入(inject),但我不知道可以将 @EJB 注入(inject)放在哪里。

那么使用 DAO 工厂模式注入(inject) EntityManager 的正确方法是什么?

最佳答案

为了使 EJB 表现得像 EJB,您不应该创建它们。 EJB 容器负责创建它们并确保正确应用每个装饰(事务、注入(inject))。

EJB 容器已经为您实现了工厂模式。您应该使用它的功能来获得特定的实现(我没有使用独立 openEJB 的经验,但在完整的 Java EE 环境中,CDI 和 JNDI 提供了所需的功能)。

看来您应该能够使用 JNDI 来检索预期的 EJB。

如果 EJB 的名称默认为类名称,则此代码应该可以工作:

CustomerDAO friend = (CustomerDAO) new InitialContext().lookup("java:comp/env/OracleCustomerDAO");

( full doc )

对于 CDI 方式,您可以使用其替代机制( TommEE doc )。

关于模式的一点说明。它们应该用来解决痛点。 J2EE 模式已被记录下来以克服 J2EE 的限制。在 Java EE 的 future 版本中,他们引入了以更可用的方式实现不同模式的元素。 JAP 是其中的一部分。

JPA 是 Domain Store pattern 的实现。在Domain Store图中你可以清楚地看到它已经包含了DAO。那么在已经包含 DAO 的抽象之上创建 DAO 有什么意义呢?

关于java - 如何让EntityManager在DAO Factory中正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36470525/

相关文章:

java - 错误 HTTP 状态 400 - 客户端发送的请求在语法上不正确。更新

java - 在根项目中找不到任务 'generateApolloSources'

java - Hibernate:使用别名获取列

java - Hibernate 5 给出错误 : must have same number of columns as the referenced primary key

jaxb - EclipseLink MOXy 不编码用 @XMLAttribute 注释的子图字段

java - 将列表作为参数传递给 JPQL 命名查询不起作用

java - 在访问器(getter)方法上使用转换器时出现异常

java - 将对象数组输出为字符串时如何处理 NullPointerException?

Java 语音识别 API

java - 读取实体时更改 DAO/Repository 中的特定值