2016-04-07 4 views
0

Я хочу реализовать шаблон DAO, описанный here с EclipseLink и OpenEJB. Первая попытка с изображением 9.1, указанная в ссылке, отлично работает. Код типа:Как заставить EntityManager правильно работать в DAO Factory?

// 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. Когда я отслеживаю код с помощью отладчика, я обнаружил, что EntityManager в OracleCustomerDAO - null. Я думаю, это потому, что я не делал никаких инъекций @EJB на моем новом сервисе, но я понятия не имею, где я могу разместить эту инъекцию @EJB.

Итак, каков правильный способ введения EntityManager с помощью шаблона DAO Factoryories?

ответ

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. На диаграмме Domain Store вы можете ясно видеть, что он уже включает DAO. Итак, в чем смысл создавать DAO поверх абстракции, которая уже включает DAO?

+0

Спасибо за ответ, я прочитаю документы и попытаюсь изменить свой код, чтобы он работал (и я приму ответ, если мне удастся, или я обновлю статус в комментарии). В части шаблона я прочитал много тем о том, как JPA убил DAO или что-то в этом роде, и об этом много разных мнений. Я все еще не уверен, что шаблон DAO хорош или нет с JPA, может быть, когда-нибудь компания захочет избавиться от JPA, а шаблон DAO будет проще реорганизовать, потому что он разделяет логическую часть и часть обработки данных? – Nier

+0

Если вы замените JPA другой картой, 9,99% шансов, что ваша абстракция «DAO» больше не будет работать, и вам нужно будет обновить интерфейсы DAO и бизнес-логику, используя ее. Для замены использования JPA в бизнес-логике потребуется столько же времени, сколько в DAO. Если вам нужно кое-что сделать в манере JPA, вы можете абстрагировать эту часть в отдельном классе. Но 95% использования JPA - это простой CRUD, который легко обновить. – Kazaag

+0

Я заменил 'return new OracleCustomerDAO();' с возвратом (CustomerDAO) new InitialContext(). Lookup ("java: comp/env/OracleCustomerDAO"); 'в' getCustomerDAO() 'функция. Однако он дает мне «NamingException», в котором указано ** Имя «comp/env/OracleCustomerDAO» не найдено. ** – Nier