代码之家  ›  专栏  ›  技术社区  ›  Peter

在Grails中使用HibernateCriteriaBuilder时,为什么要获取“空值被分配给”错误消息的基元类型setter的属性?

  •  76
  • Peter  · 技术社区  · 15 年前

    在我的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)
    
    11 回复  |  直到 6 年前
        1
  •  126
  •   Community CDub    8 年前

    根据这个 SO thread 解决方案是使用非基元包装器类型;例如, Integer 而不是 int .

        2
  •  40
  •   MattC Holger    12 年前

    不能将空值赋给基元类型,如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列设置为不允许空值,要么使用包装类。

        3
  •  11
  •   Nhat Dinh    12 年前

    基元类型不能为空。因此,解决方案是用tablename.java文件中的Primitive Wrapper类替换Primitive类型。 例如:

    @Column(nullable=true, name="client_os_id")
    private Integer client_os_id;
    
    public int getClient_os_id() {
        return client_os_id;
    }
    
    public void setClient_os_id(int clientOsId) {
        client_os_id = clientOsId;
    }
    

    参考 http://en.wikipedia.org/wiki/Primitive_wrapper_class 以查找Primivite类型的包装类。

        4
  •  5
  •   Buhake Sindi Tesnep    9 年前

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

    private Integer num;
    
    public Integer getNum()...
    
    public void setNum(Integer num)...
    
        5
  •  5
  •   codechefvaibhavkashyap    9 年前

    我会用一个例子来帮助你理解。假设您有一个关系表(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空

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

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

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

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

        6
  •  2
  •   Kamiel Ahmadpour    11 年前

    @dinh nhat,您的setter方法看起来错误,因为您再次将基元类型放在那里,它应该是:

    public void setClient_os_id(Integer clientOsId) {
    client_os_id = clientOsId;
    }
    
        7
  •  2
  •   am0wa    9 年前

    要么完全避免 null 在数据库中通过 NOT NULL 在休眠实体中通过 @Column(nullable = false) 相应地或使用 Long 包装而不是你 long 基元。

    基元不是对象,因此无法分配 无效的 对它。

        8
  •  2
  •   Michael Gaskill Surya    9 年前

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

    public void setPhoneNumber(Long phoneNumber) {
        if (phoneNumber != null)
            this.phoneNumber = phoneNumber;
        else
            this.extension = 0l;
    }
    
        9
  •  1
  •   Aravinthan K    8 年前

    确保你的数据库 我的属性 字段包含空而不是零。

        10
  •  1
  •   4302836    7 年前

    有两条路

    • 确保不允许使用db列 null
    • 基本类型变量的用户包装类,如 private int var; 可以初始化为 private Integer var;
        11
  •  0
  •   Israelm    6 年前

    不要在您的 实体类 使用各自的包装纸。这样可以解决这个问题。

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

    推荐文章