Я правильно использую EJB? - PullRequest
       10

Я правильно использую EJB?

2 голосов
/ 22 апреля 2010

Я использую стек JEE6, включая JPA 2.0, JSF 2.0, EJB 3.1 и т. Д.

Моя архитектура настроена следующим образом:

У меня есть JPA с аннотациями JPA, использующими hibernate в качестве моего поставщика JPA. У меня есть JSF Managed bean, которые соответствуют моим страницам facelet / xhtml. У меня есть EJB, которые обрабатывают все мои запросы к базе данных.

На моих страницах XHTML есть JSF EL, который делает вызовы моим управляемым bean-компонентам. Мои управляемые bean-компоненты содержат ссылки на мои объекты DAO, которые управляются EJB-компонентами. Например, у меня есть пользовательский объект, который сопоставлен с таблицей БД. У меня есть пользовательский EJB, который обрабатывает все операции CRUD, которые возвращают пользователей. У меня есть страница, которая редактирует пользователя. Рабочий процесс высокого уровня будет следующим: перейти на страницу редактирования пользователя -> EL вызывает метод, расположенный в управляемом компоненте, который загружает пользователя. Метод вызывает userEJB.loadUser (user) из EJB, чтобы получить пользователя из базы данных. Пользователь редактируется и отправляет -> в управляемом компоненте вызывается функция, которая вызывает функцию в EJB для сохранения пользователя. и т.д.

У меня проблемы с доступом к моим данным на страницах JSF с использованием EJB. У меня много проблем с ленивыми ошибками инициализации, которые, я считаю, связаны с тем, как я их настроил.

Например, у меня есть клиентская сущность, у которой есть список пользователей, которые загружаются лениво. Чтобы получить клиент, которого я вызываю в моем EJB-методе, который попадает в базу данных, находит клиента и возвращает его. Позже я хочу получить доступ к этому списку клиентов клиентов, для этого мне нужно вернуться к EJB, вызвав какой-то метод для загрузки этих пользователей (так как они загружаются лениво). Это означает, что мне нужно создать метод, такой как

public List<User> getUserListByClient(Client c)
{
    c = em.merge(c); return c.getUserList();
}

Единственная цель этого метода - загрузить пользователей (и я даже не уверен, что этот подход хорош или работает). Если бы я сам занимался управлением сессиями, я хотел бы просто оставить сессию открытой для всего запроса и получить доступ к свойству напрямую, это было бы хорошо, так как сессия была бы открыта в любом случае, кажется, что в EJBs есть еще один дополнительный уровень косвенности что осложняет мне жизнь.

Мне нравятся EJB, поскольку мне нравится тот факт, что они контролируются контейнером, объединяются в пул, предлагают управление транзакциями бесплатно и т. Д. Однако у меня возникает ощущение, что я их неправильно использую, или я настроил свое приложение JSF неправильно.

Любая обратная связь будет принята с благодарностью.

спасибо,

Ответы [ 2 ]

2 голосов
/ 22 апреля 2010

Если бы я занимался управлением сессиями Я бы хотел оставить сеанс открыт для всего запроса и получить доступ к собственности напрямую, это было бы хорошо, как сессия будет все равно открыть

Действительно, это открытый сеанс в представлении (также называемый открытым EntityManager в представлении). Он также может быть использован с EJB. В идеале, транзакции должны управляться на бизнес-уровне / EJB, так что это можно увидеть как небольшое отклонение от архитектуры чистого уровня. Но это решает проблему ленивой загрузки в представлении и легко.

В противном случае вы должны обязательно загрузить информацию, которая будет использоваться после завершения транзакции. Или вы можете положиться на DTO, но тогда это становится громоздким.

Вот еще две ссылки, которые охватывают тему и обсуждают плюсы и минусы и альтернативы:

1 голос
/ 24 апреля 2010

Ваше использование кажется хорошим. Просто помните, что em.merge (c) может сохранить изменения, внесенные в Client c, в базу данных. Если вы просто хотите получить UserList клиента c без сохранения изменений, внесенных в клиент c, то вы можете сделать это:

public List<User> getUserListByClient(Client c)
{

     Client client = em.find(Client.class, c.clientId);
     return client.getUserList();

}

Или, что лучше, просто отправьте идентификатор клиента в getUserListByClient вместо того, чтобы передавать полный объект клиента, просто чтобы сэкономить немного памяти :)

...