如何让 EntityManager 在 DAO Factories 中正常运行?
How to make EntityManager works properly in DAO Factories?
我想用 EclipseLink 和 OpenEJB 实现描述 here 的 DAO 模式。 link 中列出的图 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);
}
}
但是,当我想适配工厂模式时,我不知道怎样做才是正确的。我在 link 中编写了代码作为教程并添加了两个 类 像这样:
// 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 的经验,但在完整的 Java EE 环境中,CDI 和 JNDI 正在提供所需的功能)。
看来您应该能够使用 JNDI 来检索预期的 EJB。
如果 EJB 的名称默认为 class 名称,则此代码应该有效:
CustomerDAO friend = (CustomerDAO) new InitialContext().lookup("java:comp/env/OracleCustomerDAO");
(full doc)
对于CDI方式,您可以使用其替代机制(TommEE doc)。
简单介绍一下模式。它们应该用于解决痛点。 J2EE 模式已被记录以克服 J2EE 的局限性。在 Java EE 的未来版本中,他们引入了以更有用的方式实现不同模式的元素。日本是其中的一部分。
JPA 是 Domain Store pattern 的一个实现。在 Domain Store 图中,您可以清楚地看到它已经包含 DAO。那么在已经包含 DAO 的抽象之上创建 DAO 有什么意义呢?
我想用 EclipseLink 和 OpenEJB 实现描述 here 的 DAO 模式。 link 中列出的图 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);
}
}
但是,当我想适配工厂模式时,我不知道怎样做才是正确的。我在 link 中编写了代码作为教程并添加了两个 类 像这样:
// 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 的经验,但在完整的 Java EE 环境中,CDI 和 JNDI 正在提供所需的功能)。
看来您应该能够使用 JNDI 来检索预期的 EJB。
如果 EJB 的名称默认为 class 名称,则此代码应该有效:
CustomerDAO friend = (CustomerDAO) new InitialContext().lookup("java:comp/env/OracleCustomerDAO");
(full doc)
对于CDI方式,您可以使用其替代机制(TommEE doc)。
简单介绍一下模式。它们应该用于解决痛点。 J2EE 模式已被记录以克服 J2EE 的局限性。在 Java EE 的未来版本中,他们引入了以更有用的方式实现不同模式的元素。日本是其中的一部分。
JPA 是 Domain Store pattern 的一个实现。在 Domain Store 图中,您可以清楚地看到它已经包含 DAO。那么在已经包含 DAO 的抽象之上创建 DAO 有什么意义呢?