1

我正在尝试使用 JPA 和 JSF 实现简单的列表和编辑页面,但是尽管数据库中有 4 条记录,但列表没有返回任何行。堆栈跟踪中没有错误,因此我很难找到根本原因。这一次,我可以说没有调用 init 方法。你们能帮我一把吗?

Usuario.java

package br.com.jpajsf.model.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Usuario {

@Id
@GeneratedValue
private int idUsuario;

private String dsIdentificador;

private String dsSenha;

private String dsSal;

private String dsNome;

private String dtNascimento;
// getters, setters, hashCode e equals.

UsuarioServices.java

package br.com.jpajsf.persistence;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import br.com.jpajsf.model.entity.Usuario;

@Stateless
public class UsuarioServices {
@PersistenceContext
private EntityManager em;

public List<Usuario> getUsuarios() {
    return em.createQuery("select u from Usuario u", Usuario.class)
            .getResultList();
}

public Usuario find(String id) {
    return em.find(Usuario.class, Integer.parseInt(id));
}

public void persist(Usuario u) {
    em.persist(u);
}
}

UsuarioBean.java

package br.com.jpajsf.domain;

import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

import br.com.jpajsf.model.entity.Usuario;
import br.com.jpajsf.persistence.UsuarioServices;

@ViewScoped
@Named
public class UsuarioBean {
@Inject
private UsuarioServices usuarioServices;

private Usuario usuario;
private List<Usuario> usuarios;

@PostConstruct
public void init() {
    Map<String, String> params = FacesContext.getCurrentInstance()
            .getExternalContext().getRequestParameterMap();

    if (!params.isEmpty()) {
        try {
            usuario = usuarioServices.find(params.get("idUsuario"));
        } catch (NumberFormatException e) {
        }
    }

    if (usuario == null) {
        usuario = new Usuario();
    }

    setUsuarios();
}

public List<Usuario> getUsuarios() {
    if (usuarios == null) {
        setUsuarios();
    }
    return usuarios;
}

public void setUsuarios() {
    this.usuarios = usuarioServices.getUsuarios();
}

public Usuario getUsuario() {
    return usuario;
}

public void setUsuario(Usuario usuario) {
    this.usuario = usuario;
}

public String salvar(Usuario u) {
    usuarioServices.persist(u);
    return "listar";
}
}

listar.xhtml

<h:head>
    <title>Cadastro de usuários</title>
</h:head>
<h:body>
    <h:form>
        <h:dataTable value="#{usuarioBean.usuarios}" var="usuario" border="1">
            <h:column>
                <f:facet name="header">ID</f:facet>
                #{usuario.idUsuario}
            </h:column>
            <h:column>
                <f:facet name="header">Email</f:facet>
                #{usuario.dsIdentificador}
            </h:column>
            <h:column>
                <f:facet name="header">Senha</f:facet>
                #{usuario.dsSenha}
            </h:column>
            <h:column>
                <f:facet name="header">Sal</f:facet>
                #{usuario.dsSal}
            </h:column>
            <h:column>
                <f:facet name="header">Nome</f:facet>
                #{usuario.dsNome}
            </h:column>
            <h:column>
                <f:facet name="header">Data Nascimento</f:facet>
                #{usuario.dtNascimento}
            </h:column>
            <h:column>
                <f:facet name="header">Opções</f:facet>
                <h:commandLink value="editar" action="editar?faces-redirect=true&amp;includeViewParams=true">
                    <f:setPropertyActionListener target="#{usuarioBean.usuario.idUsuario}" value="#{usuario.idUsuario}"/>
                </h:commandLink>
            </h:column>
        </h:dataTable>
    </h:form>
</h:body>
</html>

已经谢谢了!

4

2 回答 2

2

鉴于您的项目是 Java EE6 项目。要激活 CDI bean,您需要在类路径中包含文件 beans.xml。@Named 唯一的功能是使您的 JSP/JSF 页面中的 EL 可以访问 CDI bean。CDI bean 合格范围是:

  • javax.enterprise.context.RequestScoped;
  • javax.enterprise.context.ConversationScoped;
  • javax.enterprise.context.SessionScoped;
  • javax.enterprise.context.ApplicationScoped;
  • javax.enterprise.context.Dependent;如果指定了 non,则这是默认值。

为了保持一致,您要坚持上述范围之一。请在下面找到 JSR-299 规范的报价 - 第 58 页 -。它描述了最适合 JSF 框架的范围

对话上下文由内置钝化范围类型@ConversationScoped 的内置上下文对象提供。对话范围在任何 JSF 面孔或非面孔请求的所有标准生命周期阶段都处于活动状态。

对话上下文提供对与特定对话关联的状态的访问。每个 JSF 请求都有一个关联的对话。该关联由容器根据以下规则自动管理:

  • 任何 JSF 请求都只有一个关联的对话。
  • 与 JSF 请求关联的对话在恢复视图阶段开始时确定,并且在请求期间不会更改。

长话短说:

确保 beans.xml 在类路径上后,请将 ViewScoped 替换为 javax.enterprise.context.ConversationScoped。

编辑:

我忘了说钝化。事实上,您的代码只接受“javax.enterprise.context.RequestScoped”,这对于演示目的来说是可以的。另一方面,ConversationScoped 和 SessionScoped bean 都需要实现 Serializable 才能实现钝化。因此,要使您的代码成为 ConversationScoped,bean UsuarioBean 及其所有成员属性也必须实现 Serializable。

于 2014-02-17T05:13:28.313 回答
1

我在您的代码中看到了一个错误。@Named 与

import javax.faces.view.ViewScoped;

并不是

import javax.faces.bean.ViewScoped;

用于@ManagedBean

于 2014-02-15T23:52:59.240 回答