我想用数据库中的一些值填充一个简单的h:datatable标签。但是我得到一个异常,我找不到是什么原因:
. lang。NumberFormatException:对于输入字符串:"url"
我是这样创建数据表的:
<h:form>
<h:dataTable value="#{managementBB.retrieveRecords()}" var="record">
<h:column>
<f:facet name="header">URL</f:facet>
#{record.url}
</h:column>
<h:column>
<f:facet name="header">Submition date</f:facet>
#{record.submitionDate}
</h:column>
<h:column>
<f:facet name="header">Unacceptable</f:facet>
#{record.unnaceptableContent}
</h:column>
<h:column>
<f:facet name="header">Option</f:facet>
Something
</h:column>
</h:dataTable>
</h:form>
这是本页背后的后台bean:
@Named("managementBB")
@SessionScoped
public class ManagementBB implements Serializable{
@EJB
private ILinkManagerEJB linkManagerEJB;
public List<Record> retrieveRecords() {
return linkManagerEJB.retrieveRecords();
}
}
这是访问数据库以获取数据的EJB:
@Stateless(name = "ejbs/LinkManagerEJB")
public class LinkManagerEJB implements ILinkManagerEJB {
@PersistenceContext
private EntityManager entityManager;
public List<Record> retrieveRecords() {
Query allRecords = entityManager.createNamedQuery("allrecordinfo");
return (List<Record>) allRecords.getResultList();
}
}
最后这是代表数据库中一行的JPA实体:
@Entity
@NamedQueries({@NamedQuery(name = "allrecordinfo",
query = "SELECT r.url, r.submitionDate, r.unnaceptableContent FROM Record r")})
public class Record {
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private String url;
@Column(nullable = false)
private String submitionDate;
@Column(nullable = false)
private boolean unnaceptableContent;
//Get set methods ...
}
正如你所看到的,它看起来很简单,我以前这样做过,但现在我很困惑,我不知道为什么不工作。你能帮我找出我的错误吗?
注意:我非常确信查询语法是ok的(我在eclipse的剪贴簿中测试过)
这表明. lang。NumberFormatException:用于输入字符串:"url"
#{record.url}
Record
实际上是和Object[]
,因为它期望一个像这样的整数索引
#{record[0]}
确实,您的查询是错误的,它没有选择Record
,而只是单个字段,这将返回具有单个字段而不是List<Record>
的List<Object[]>
。强制转换(会产生一个警告)并不能阻止/改变这个
查询不正确。
@NamedQueries({ @NamedQuery(name = "allrecordinfo", query = "SELECT r FROM Record r") })
@Entity
public class Record {
}
为了防止将来出现类似的错误,您应该使用类型化查询而不是强制类型转换。
对无类型查询的查询结果进行强制转换是一种相当老的做法(实际上是从2006年开始),不应该再使用了。
一些额外的提示:您不必为EJB指定显式名称。@Stateless就够了。CDI bean也是如此,它将获得一个默认名称。
然后,您可能需要重新考虑EJB接口的名称。首字母"I"最近不太受欢迎。
另外,为从后台bean返回的数据创建getter更为常见。之后可以使用值绑定(在EL表达式中提交())。
最后,您可能希望将对EJB的调用移动到@PostConstruct方法,因为JSF可能多次调用您的后台bean的方法,这现在将导致每次都调用DB。如果您这样做,您的bean也应该在视图范围内最好,但这意味着您要么必须从CDI bean转换为常规的JSF托管bean,要么使用seam 3。