java - JSF/JPA 错误 : The class 'java.lang.String' does not have the property

标签 java jsf jpa jsf-2 ejb

我正在显示数据库中的足球运动员列表,用户可以选择该列表并将其添加到 ArrayList 中。显示所有玩家效果很好,但不适用于选定的玩家。当我请求普通对象或其哈希码时,它返回它的值,但是一旦我引用与 Player 实体相关的属性,它就会给出错误。有人吗?

支持 bean

@Named
@SessionScoped
public class PlayerBean implements Serializable {

private static final long serializableUID = 1L;
@Inject
PlayerFacade facade;

private List<Player> allPlayers;
private List<Player> selectedPlayers;

public PlayerBean() {
}

public List<Player> getAllPlayers() {
    return facade.findAll();
}


public List<Player> getSelectedPlayers() {
    return selectedPlayers;
}

public void setSelectedPlayers(List<Player> selectedPlayers) {
    this.selectedPlayers= selectedPlayers;
}

}

实体类

@Entity
@Table(name = "player")
@XmlRootElement

public class Player implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "PlayerID")
private Integer playerID;
@Size(max = 45)
@Column(name = "Name")
private String name;
@Size(max = 45)
@Column(name = "Position")
private String position;
// @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
@Column(name = "Weight")
private BigDecimal weight;

public Player() {
}

public Player(Integer playerID) {
    this.playerID = playerID;
}

public Integer getPlayerID() {
    return playerID;
}

public void setPlayerID(Integer playerID) {
    this.playerID = playerID;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getPosition() {
    return position;
}

public void setPosition(String position) {
    this.position = position;
}

public BigDecimal getWeight() {
    return weight;
}

public void setWeight(BigDecimal weight) {
    this.weight = weight;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (playerID != null ? playerID.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Player)) {
        return false;
    }
    Player other = (Player) object;
    if ((this.playerID == null && other.playerID != null) || (this.playerID != null && !this.playerID.equals(other.playerID))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "playerID=" + playerID + " ]";
}

}

JSF 页面

<h:form id="allPlayers" style="text-align: center;" >
                    <h:selectManyCheckbox value="#{playerBean.selectedPlayers}">
                     <f:selectItems value="#{playerBean.allPlayers}" var="p" itemLabel="#{p.name} #{p.position} #{p.weight}" />
                    </h:selectManyCheckbox>
                    <h:commandButton value="Add to Team" action="team"/>
                </h:form>
            </p>
            <p>
                <h:form id="selectedPlayers" style="text-align: center;" >
                    <h:dataTable value="#{playerBean.selectedPlayers}" var="players">
                        <h:column>
                            #{players}
                        </h:column>
                        <h:column>
                            #{players.name}
                        </h:column>
                    </h:dataTable>
                    <h:commandButton value="Set Team" action="team"/>
                </h:form>

错误消息

javax.el.ELException: /team.xhtml: The class 'java.lang.String' does not have the property 'name'.
at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:88)
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
at com.sun.faces.renderkit.html_basic.TableRenderer.renderRow(TableRenderer.java:385)
at com.sun.faces.renderkit.html_basic.TableRenderer.encodeChildren(TableRenderer.java:162)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:443)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:724)

最佳答案

如果您考虑以下概念,您就会理解您的问题:

  1. 在 HTTP 协议(protocol)下,客户端与服务器之间的通信仅通过纯字符串进行处理。因此,与表单一起提交的所有值都以字符串形式发送。
  2. 您将您的 Collection 声明为 List<Player> 。因为它的值将通过运行时且基于反射的 EL 设置。当 EL 完成其工作时,您的 Collection 类型信息将已被删除,并且将变得简单 List .
  3. 鉴于此信息,EL 接收一个字符串并尝试设计支持模型的类型,但它不能,因为当时没有可用的类型信息,因此它将写入从客户端接收到的字符串。
  4. 您没有指定itemValue <f:selectItems> 的属性标签,所以我认为它是在表单提交到其默认值之后写入的,很可能 p,toString()在你的情况下。

如果您调试代码并查看已提交的内容,您会发现您的列表实际上是由字符串填充的。现在你应该明白问题的原因和抛出的异常了,因为 String 中确实没有 name 属性。类。

至于解决方案,为了保持正常运行,基本上需要做两件事:

  1. 指定 itemValue<f:selectItems>明确标记为 itemValue="#{p}"告诉 JSF 期待您的播放器实例;
  2. 指定 Converter明确地使用,例如 converter <h:selectManyCheckbox> 的属性标签。这可以通过提供您自己的 @FacesConverter class 来完成,或者,如果您不介意使用优秀的 OmniFaces JSF 实用程序库,只需使用它的 SelectItemsConverter as converter="omnifaces.SelectItemsConverter" 。这将使 JSF 能够将指定的类实例填充到您的支持列表中。

关于java - JSF/JPA 错误 : The class 'java.lang.String' does not have the property,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20535618/

相关文章:

java - 从Java进程访问子进程控制终端

java - 如何从 Java 应用程序中传输实时视频?

java - 丰富 :listShuttle error when using complex object

java - 如何在jsf中使用 session 过滤器作为登录表单

java - JSF - selectManyListbox 附带已选择的项目

java - 从模式窗口调用 Wicket setResponsePage() 时如何打败浏览器对话框弹出窗口?

java - 如何使用TypeToken获取类型参数?

java - 在类路径中找不到任何 META-INF/persistence.xml 文件 Java - Dynamic Web Project

java - JPA 标准 API。使用带有参数的sql函数调用查询

postgresql - 减少对包含实体的 JPQL POJO 的查询次数