JPA ленивая загрузка коллекций в представлении JSF - лучший способ, чем использование фильтров? - PullRequest
1 голос
/ 30 марта 2012

В настоящее время я использую шаблон Transaction View, чтобы сделать возможным отложенную загрузку коллекций в представлениях.

У меня есть следующее в web.xml

<filter>
  <filter-name>view</filter-name>
  <filter-class>com.jasoni.ViewFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>view</filter-name>
  <url-pattern>*.xhtml</url-pattern>
</filter-mapping>

И класс Filter имеет следующий ...

public class ViewFilter implements Filter {
  @Resource UserTransaction tx;

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
      tx.begin();
      chain.doFilter(request, response);
    }
    //catch here
    finally {
      //another try-catch
      tx.commit();
    }
  }
}

Тогда, предполагая, что у меня есть следующий (довольно надуманный) боб

@ManagedBean
@RequestScoped
public class DepartmentEmployees {
  @EJB
  private DepartmentServiceBean deptService;
  @ManagedProperty(value="#{param.deptId}")
  private Integer deptId;
  private Department dept;

  @PostConstruct
  public String init() {
    dept = deptService.findById(deptId);
  }
}

Я могу сделать что-то подобное на мой взгляд (файл .xhtml)

<ul>
<c:forEach var="emp" items="#{departmentEmployees.dept.employees}">
  <li>#{emp.firstName} #{emp.lastName}</li>
</c:forEach>
</ul>

Просто интересно, знает ли кто-нибудь другой способ выполнить то же самое без использования фильтров (или сервлетов).

1 Ответ

5 голосов
/ 30 марта 2012

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

Вы не много пишете о своем стеке инфраструктуры / технологий, но я предполагаю, что вы находитесь на сервере Java EE 6.

Я обычно использую EntityManger в расширенном режиме и сбрасываю его транзакциями, которые я явно контролирую, аннотируя только определенные методы моего бизнес-фасада.Взгляните на этот пример (взят из Адам Бьен - Шаблоны Java EE реального мира, переосмысление передового опыта ):

@Stateful
@TransactionAttribute(TransactionAttributeType.NEVER)
public class BookFacadeBean implements BookFacade {
    @PersistenceContext(type=PersistenceContextType.EXTENDED)
    private EntityManager em;
    private Book currentBook;

    public Book find(long id){
        this.currentBook = this.em.find(Book.class, id);
        return this.currentBook;
    }
    public void create(Book book){
        this.em.persist(book);
        this.currentBook = book;
    }
    public Book getCurrentBook() {
        return currentBook;
    }
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void save(){
        //nothing to do here
    }
}

Следующим уровнем в этом подходе будет привязка EntityManagerв область разговора CDI.Посмотрите (а) Сварка (b) Стойкость шва 3 для дальнейшего обсуждения этой темы.

Это скорее грубый набросок альтернативы, чемподробные инструкцииЯ надеюсь, что этот уровень информации - то, о чем вы спрашивали - не стесняйтесь задавать дополнительные вопросы.: -)

...