【问题标题】:Can't understand <p:dataTable> updating process无法理解 <p:dataTable> 更新过程
【发布时间】:2012-10-06 04:15:06
【问题描述】:

我有以下 xhtml 文档:

  <h:body>
   <ui:composition template="templates/layout.xhtml">
      <ui:define name="content">
        <c:if test="#{sessionBean.userCode > 0}">
          <h:form id="findStudentForm">
            <p:outputPanel id="resultsPanel">
              <c:if test="#{studentsBean.student != null}">
                <h2><h:outputText value="#{studentsBean.student.fullName}"/></h2>
                <h3>Personal data</h3>
                  . . .
                <p align="center">
                <p:commandButton value="Search students" update="@form">
                  <f:setPropertyActionListener value="#{null}" 
                    target="#{studentsBean.student}"/>
                </p:commandButton>
                </p>
              </c:if>
              <c:if test="#{studentsBean.student == null}">
                <h2>Student search</h2>
                  . . .
                <p align="justify">
                  First name
                  <h:inputText value="#{studentsBean.pattern}"/>
                  <p:commandButton value="Поиск" update="resultsPanel"/>                  
                </p>
                <p:dataTable id="resultsTable" var="student" 
                   value="#{studentsBean.studentsList}" 
                             widgetVar="studentsTable" emptyMessage="No records found">
                  . . . 
                  </p:column>
                  <p:column headerText="Actions">
                    <p:commandButton value="Details" update="@form">
                      <f:setPropertyActionListener value="#{student}" 
                        target="#{studentsBean.student}"/>
                    </p:commandButton>
                  </p:column>  
                </p:dataTable>
              </c:if>
            </p:outputPanel>
          </h:form>
        </c:if>
        <c:if test="#{sessionBean.userCode == 0}">
          <ui:include src="templates/include/error.xhtml"/>
        </c:if>
      </ui:define>  
    </ui:composition>
  </h:body>

我还有以下托管 Bean (StudentsBean): . . .

@Named(value = "studentsBean")
@RequestScoped
public class StudentsBean {

  @Inject
  SessionBean session;
  private Student student = null;
  private String pattern = "";
  private String groupName = "";
  @Inject
  private StudentInterface studentProvider;

  . . .

  public String getPattern() {
    return pattern;
  }

  public void setPattern(String pattern) {
    this.pattern = pattern;
  }

  public List<Student> getStudentsList() {
    List<Student> result = new ArrayList<Student>();
    if (studentProvider != null) {
      try {
        result = studentProvider.findStudents(pattern);
      } catch (StudentException e) {
        session.printError(e.getMessage());
      }
    }
    return result;
  }
  . . .

最后,我有一个 StudentProvider 类:

public class StudentProvider implements StudentInterface {

  private Connection connection = null;

   . . .

  @Override
  public List<Student> findStudents(String pattern) throws StudentException {
    List<Student> result = new ArrayList<Student>();
    String addon = "";
    if (pattern.trim().isEmpty()) {
      addon = "TOP 10 ";
    }
    try {
      PreparedStatement statement = connection.prepareStatement(
              "SELECT " + addon + "st_pcode, gr_Name, st_FullName "
              + "FROM students, groups WHERE (st_grcode = gr_pcode) AND (st_FullName LIKE ?) "
              + "ORDER BY gr_Name, st_FullName;", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      statement.setString(1, pattern + "%");
      ResultSet rs = statement.executeQuery();
      while (rs.next()) {
        result.add(getStudent(rs.getString("st_pcode")));
      }
      rs.close();
      statement.close();
    } catch (Exception e) {
      throw new StudentException("Error reading list: " + e.getMessage());
    }
    return result;
  }

  public StudentProvider() throws StudentException {
    try {
    ConnectionProvider provider = new ConnectionProvider();
    connection = provider.getConnection();
    } catch (ConnectionException e) {
      throw new StudentException("Connect error: " + e.getMessage());
    }
  }

  @Override
  public void finalize() throws Throwable {
    connection.close();
    super.finalize();
  }
}

如果变量“pattern”为空字符串,PreparedStatement 返回 10 个“first”记录。但是如果“模式”有内容——PreparedStatement 会找到一些记录。在调试期间,PreparedStatement 似乎运行良好并返回结果集,但在“sultsTable”中没有显示记录。另外,我发现,在更新处理方法时

studentProvider.findStudent(pattern)

多次调用。我认为,方法调用的数量取决于“resultsTable”中的记录数。

在注入之前,使用硬链接对象一切正常。怎么了?

顺便说一句,我不能理解一件事。说,我有一个按钮

<p:commandButton value="Details" update="@form">
    <f:setPropertyActionListener value="#{student}" 
        target="#{studentsBean.student}"/>
</p:commandButton>

在“resultsTable”的每条记录中(更多详细信息请参见之前的 xhtml 列表)。我发现,这个按钮有时不起作用。 如果 resultsTable 开头为空 - 按钮不起作用,但如果 resultsTable 不为空 - 按钮起作用。那么如何让按钮始终工作呢?

【问题讨论】:

  • 如果不阅读整个 q' ,最好将数据放在视图或会话范围内,否则很难让它以正确的方式工作
  • 我解决了搜索结果中数据丢失的问题。这是一个例外,处理不当。我现在只需要知道-为什么dataTable数据的getter方法调用了几次?调用次数取决于多少以及如何最大限度地减少调用次数。
  • 干脆不要在getter方法中做业务逻辑!
  • @BalusC 谢谢!我还很难以 JSF 风格思考。我会记住这条黄金法则。

标签: ajax jakarta-ee jsf-2 primefaces


【解决方案1】:

更好的方法是(只是一个草图):

// an action method in your backing bean.
// This will call your search method and set the values behid your dataTable
public void searchStudents(String pattern) {
    setStudentsList(findStudent(pattern));
}

调用结束后更新你的dataTable:

<p:commandButton update="resultsTable" action=#{studentProvider.findStudent(pattern)}"

回答您的第二个问题:Why JSF calls getters multiple times,这意味着将您的业务逻辑方法放入 getter(没有延迟加载)似乎是一个坏主意(另一个相关问题:JSF calling setter & getter multiple times)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    相关资源
    最近更新 更多