【问题标题】:Why JPA entity throws exception when rowKey attribute is the primary key?为什么当 rowKey 属性为主键时 JPA 实体会抛出异常?
【发布时间】:2018-12-01 08:32:21
【问题描述】:

我正在使用 JavaEE 构建一个非常简单的 Java 全栈应用程序,因此我使用带有 Prime Faces 6.2 的 JSF 在前端渲染 xthml,在后端渲染 EJB、JPA 和 Hibernate 和 postgresql,但是,当我从 Prime Faces 的 dataTable 组件中设置了 rowKey="#{person.id}"。抛出下一个异常。

"00:13:36,307 错误 [io.undertow.request](默认任务 55)UT005023:对 /javaee-app/faces/listPersons.xhtml 的异常处理请求:javax.servlet.ServletException ... 由:java.lang.NullPointerException"

listPersons.xhtml
Prime Faces DataTable Component(opening tag and its attributes)

<p:dataTable id="persons"
                 value="#{personBean.persons}"
                 var="person"
                 editable="true"
                 rowKey="#{person.id}"
                 selection="#{personBean.personSelected}"
                 selectionMode="single">

The exception thrown that appears when trying to render the page is this.

但是,如果我设置 rowKey="#{person.name}" 甚至 rowKey="#{person.email}" 而不是 rowKey="#{person.id}" 问题就会消失并且 xthml 页面是正确渲染。

<p:dataTable id="persons"
             value="#{personBean.persons}"
             var="person"
             editable="true"
             rowKey="#{person.name}"
             selection="#{personBean.personSelected}"
             selectionMode="single">

with rowKey="#{person.name}" or rowKey="#{person.email}" xhtml page is rendered correctly"

Postgresql Database person

模型/实体

@Entity
@Table(name = "person")
@NamedQueries({
@NamedQuery(name = "Person.findAll", query = "SELECT p FROM Person p"), 
@NamedQuery(name = "Person.findById", query = "SELECT p FROM Person p 
WHERE p.id = :id")
, @NamedQuery(name = "Person.findByName", query = "SELECT p FROM 
Person p WHERE p.name = :person_name")
, @NamedQuery(name = "Person.findByLastname", query = "SELECT p FROM 
Person p WHERE p.lastname = :lastname")
, @NamedQuery(name = "Person.findByEmail", query = "SELECT p 
FROM Person p WHERE p.email = :email")
, @NamedQuery(name = "Person.findByPhone", query = "SELECT p 
FROM Person p WHERE p.phone = :phone")})
public class Person implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 60)
@Column(name = "person_name")
private String name;

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 60)
private String lastname;

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 60)
private String email;

@Size(max = 60)
private String phone;

@OneToMany(mappedBy = "person", fetch = FetchType.EAGER)
private List<Users> users;

public Person() { }

public Person(Integer id) {
    this.id = id;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

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

public String getLastname() {
    return lastname;
}

public void setLastname(String lastname) {
    this.lastname = lastname;
}


public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getPhone() {
    return phone;
}

public void setPhone(String phone) {
    this.phone = phone;
}

public List<Users> getUsers() {
    return users;
}

public void setUsers(List<Users> users) {
    this.users = users;
}

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

@Override
public boolean equals(Object object) {
    if (!(object instanceof Person)) {
        return false;
    }
    Person other = (Person) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "Person [id = " + id + ", name=" + name
            + ", lastName=" + lastname + " email=" + email + ", phone=" + phone + "]";
}

有解决这个问题的想法吗?提前致谢

我还添加了应用服务器中生成的错误图像,在我的例子中是 Wildfly 8.2

picture1 Wildfly 8.2

picture2 Wildfly 8.2

【问题讨论】:

  • person 实体是如何填充的?我看到 5 个构造函数,一个没有 id 参数。你确定那不是用来构造实体的吗?为什么你还需要这么多?
  • 您是如何填充列表的?错误 Caused by:java.lang.NullPointerException 表示至少一个人的 ID 为空。默认情况下,JPA 调用空构造函数,而该构造函数恰好将 ID 保留为 null。也许在您支持的某个时刻,您向列表中添加了一个新人(尚未在数据库中持久化),而这个人恰好有一个空 ID?
  • @kTest 感谢您的关注,我删除了不必要的构造函数,但是,问题仍然存在,关于空构造函数,这是必要的,因为它是默认构造函数。
  • @Al1 也谢谢你,你说的有道理,但是,dataTable 根本没有呈现。如果您检查它是从名为 person 的表中填充的实体,我添加了一个包含表当前内容的屏幕截图。当要呈现 xhtml 时,它会带来数据库中的人员,因此它应该可以正常工作,但我还没有得到它。
  • 你能把 getId() 改成返回 Integer 而不是 int 吗?

标签: java hibernate jpa jsf jakarta-ee


【解决方案1】:

id 是整数类型:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

getter 在哪里返回 int:

public int getId() {
    return id;
}

将 getId 更改为返回 Integer。

【讨论】:

  • 感谢您的宝贵时间,我已更改类型,问题已解决。
  • 很高兴找到西蒙!为了进一步发展,值得一提的是,这个NullPointerExceptionthis question中的相同。关于原始类型拆箱,这些人会比我更好地回答你
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 2020-12-27
  • 2014-03-12
  • 1970-01-01
  • 2021-04-28
  • 2013-09-04
  • 1970-01-01
相关资源
最近更新 更多