如何使EntityManager在DAO工厂中正常工作?

时间:2016-04-07 08:20:49

标签: java jpa eclipselink dao openejb

我想用EclipseLink和OpenEJB实现描述here的DAO模式。链接中列出的图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 。当我使用调试器跟踪代码时,我发现EntityManager中的OracleCustomerDAOnull。我认为这是因为我在新服务中没有注射@EJB,但我不知道在哪里可以注入@EJB注射。

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

1 个答案:

答案 0 :(得分:1)

为了使EJB像EJB一样运行,您不应该创建它们。 EJB容器负责创建它们,确保每个装饰(事务,注入)都正确应用。

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的未来版本中,它们引入了在事件更实用的方式中实现不同模式的元素。 JAP是其中的一部分。

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