我想用EclipseLink和OpenEJB实现这里描述的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);
}
}
然而,当我想适应Factory模式时,我不知道什么是正确的方法
// 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
中的EntityManager
是null
。我想这是因为我在新服务中没有进行任何@EJB
注入,但我不知道@EJB
注入可以放在哪里。
那么,用DAO工厂模式注入EntityManager的正确方法是什么呢?
为了让EJB像EJB一样工作,您不应该创建它们。EJB容器负责创建它们,并确保每个装饰(事务、注入)都正确应用。
EJB容器已经在为您实现工厂模式。您应该使用它的功能来获得特定的实现(我没有独立的openEJB的经验,但在完整的JavaEE环境中,CDI和JNDI提供了所需的功能)。
看来您应该能够使用JNDI来检索期望的EJB。
如果EJB的名称默认为类名:,则此代码应该有效
CustomerDAO friend = (CustomerDAO) new InitialContext().lookup("java:comp/env/OracleCustomerDAO");
(完整文档)
对于CDI方式,您可以使用它的替代机制(TommEE-doc)。
关于图案的一个小词。它们应该用来解决一个痛点。J2EE模式已经被记录下来以克服J2EE的局限性。在JavaEE的未来版本中,他们引入了以事件更可用的方式实现不同模式的元素。日本是其中的一部分。
JPA是域存储模式的一种实现。在DomainStore图中,您可以清楚地看到它已经包含了DAO。那么,在已经包含DAO的抽象之上创建DAO有什么意义呢?