为什么我会得到一个“;为基元类型setter的属性分配了Null值;在Grails中使用HibernateCriteriaBuilder时出现错误消息

为什么我会得到一个“;为基元类型setter的属性分配了Null值;在Grails中使用HibernateCriteriaBuilder时出现错误消息,grails,gorm,Grails,Gorm,在grails域对象中使用基元属性时,出现以下错误: Null value was assigned to a property of primitive type setter of MyDomain.myAttribute org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of MyDomain.myAttribute at grails

在grails域对象中使用基元属性时,出现以下错误:

Null value was assigned to a property of primitive type setter of MyDomain.myAttribute
 org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of MyDomain.myAttribute
at grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1077)

根据这一点,解决方案是使用非原始包装类型;e、 例如,
Integer
而不是
int

不能将空值分配给基本类型,如int、long、boolean等。如果与对象中字段对应的数据库列可以为空,则字段应该是包装类,如Integer、long、boolean等

危险在于,如果数据库中没有空值,代码将正常运行,但一旦插入空值,代码就会失败

而且您总是可以从getter返回基元类型。例:

  private Integer num;

  public void setNum(Integer i) {
    this.num = i;
  }

  public int getNum() {
    return this.num;
  }
但在大多数情况下,您都希望返回包装器类


因此,要么将DB列设置为不允许空值,要么使用包装类。

基元类型不能为空。因此,解决方案是在tableName.java文件中用原始包装器类替换原始类型。 例如:


用于查找primivite类型的包装器类的引用

使用Integer作为类型,并相应地提供setter/getter

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...

@Dinh Nhat,您的setter方法看起来是错误的,因为您再次在那里放置了一个基元类型,它应该是:

public void setClient_os_id(Integer clientOsId) {
client_os_id = clientOsId;
}

确保您的数据库myAttribute字段包含null而不是零。

在数据库中通过
非null
完全避免
null
,在Hibernate实体中通过
@列(nullable=false)
相应地使用
Long
包装,而不是使用
Long
原语


原语不是对象,因此您不能将
null
赋值给它。

我将通过一个例子让您理解。假设您有一个关系表(STUDENT),它有两列,ID(int)和NAME(String)。现在,作为ORM,您将创建一个实体类,如下所示:-

package com.kashyap.default;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * @author vaibhav.kashyap
 *
 */
@Entity
@Table(name = "STUDENT")
public class Student implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -1354919370115428781L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "NAME")
    private String name;

    public Student(){

    }

    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;
    }

}
让我们假设表已经有了条目。现在,如果有人要求您添加另一列“年龄”(int)

ALTER TABLE STUDENT ADD AGE int NULL

要在预填充表中添加另一列,必须将默认值设置为NULL。这将使您在类中添加另一个字段。现在的问题是,您是使用基本数据类型还是非基本包装器数据类型来声明字段

@Column(name = "AGE")
private int age;


您必须将字段声明为非原语包装器数据类型,因为容器将尝试用实体映射表。因此,如果您不将字段声明为包装器,它将无法映射空值(默认值)&最终将抛出“将空值分配给基元类型setter的属性”异常。

将参数类型从基元更改为对象,并在setter中进行空检查。见下面的例子

public void setPhoneNumber(Long phoneNumber) {
    if (phoneNumber != null)
        this.phoneNumber = phoneNumber;
    else
        this.extension = 0l;
}
有两种方法

  • 确保不允许db列
    null
  • 基本类型变量的用户包装类,如
    private int var
    可以初始化为
    私有整数变量

不要在实体类中使用原语,而是使用它们各自的包装器。这将解决这个问题

在实体类之外,您可以使用!=其余代码流的空验证

@Column(name ="LEAD_ID")
private int leadId; 
改为

@Column(name ="LEAD_ID")
private Integer leadId; 

不要弄乱数据输入,也不必使用非基本包装器。我没有输入一些值,通过将其添加到数据库,我成功地修复了这个错误。
@Column(name ="LEAD_ID")
private int leadId; 
@Column(name ="LEAD_ID")
private Integer leadId;