JSF 2 Lifecycle
I have this code for BookModel.java:
@Entity
@Table(name = "BOOK")
@NamedNativeQuery(name = "BookModel.findBookTitle", query = "SELECT @rownum:=@rownum+1 'no', m.title, m.author开发者_运维技巧, REPLACE(SUBSTRING_INDEX(m.content, ' ', 30), '<br>', ' '), m.viewed, m.hashid FROM book m, (SELECT @rownum:=0) r WHERE m.title like 'a%'")
public class BookModel implements Serializable
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MY_SEQ_GEN")
@Column(name = "id", unique = true, nullable = false)
private Long id;
@NotNull
@Size(min = 1, max = 255)
@Column(name = "title")
private String title;
@NotNull
@Size(min = 1, max = 255)
@Column(name = "author")
private String author;
}
And BookService.java for the business layer:
@Stateless
public class BookService
{
@SuppressWarnings("unchecked")
public List<BookModel> getBook() {
Query query = entityManager.createNamedQuery("BookModel.findBookTitle");
List<BookModel> result = query.getResultList();
return result;
}
}
And BookBean.java for the presentation layer:
@ManagedBean(name = "BookBean")
@RequestScoped
public class BookBean implements Serializable
{
@EJB
private BookService bookService;
private DataModel<BookModel> book;
public DataModel<BookModel> getBook() {
return book;
}
}
And the page book.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<p:dataTable id="bookList" value="#{BookBean.book}" var="book">
...
</p:dataTable>
</html>
My question is: How can I restrict the method getBook() in BookBean to be executed only once instead of six times - presumably for each phase of JSF lifecycle. Has anyone else come across this before? Please help. Have been stuck on this for the last day without any success.
That's not possible. It should usually not harm. Getters are solely there to provide access points to bean properties, not to do some business jobs.
If you did call the @EJB
s getBook()
method inside that managed bean method like follows
public DataModel<BookModel> getBook() {
return new ListDataModel<BookModel>(bookService.getBook());
}
then this is indeed going to be expensive as it would call the DB that much times as the getter is called. You would like to do the job in the bean's constructor or @PostConstruct
instead.
@PostConstruct
public void init() {
book = new ListDataModel<BookModel>(bookService.getBook());
}
See also:
- Why JSF calls getters multiple times?
Unrelated to the concrete problem, the method name getBook()
and variable name book
is not really self-documenting since it actually contains more than one book. I'd use getBooks()
and books
instead.
精彩评论