¿Por qué obtengo un mensaje de error "Se asignó un valor nulo a una propiedad del establecedor de tipo primitivo de" cuando utilizo HibernateCriteriaBuilder en Grails?

100

Recibo el siguiente error cuando uso un atributo primitivo en mi objeto de dominio de 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)
Pedro
fuente
no estropee la entrada de datos y no tendrá que utilizar envoltorios no primitivos. No pude ingresar algunos valores y logré corregir este error agregándolo a la base de datos.
Goot

Respuestas:

168

Según este hilo SO , la solución es utilizar los tipos de envoltura no primitivos; por ejemplo, en Integerlugar de int.

Pedro
fuente
6
Todos los servicios de Codehaus han finalizado.
Priyanshu Chauhan
46

No se puede asignar un valor nulo a un tipo primitivo, como int, long, boolean, etc. Si la columna de la base de datos que corresponde al campo en su objeto puede ser nula, entonces su campo debe ser una clase contenedora, como Integer, Long, Booleano, etc.

El peligro es que su código funcione bien si no hay nulos en la base de datos, pero fallará una vez que se inserten los nulos.

Y siempre puede devolver el tipo primitivo del getter. Ex:

  private Integer num;

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

  public int getNum() {
    return this.num;
  }

Pero en la mayoría de los casos querrá devolver la clase contenedora.

Por lo tanto, configure su columna de base de datos para que no permita valores nulos o use una clase contenedora.

MattC
fuente
13

Un tipo primitivo no puede ser nulo. Entonces, la solución es reemplazar el tipo primitivo con la clase contenedora primitiva en su archivo tableName.java. Como:

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

consulte http://en.wikipedia.org/wiki/Primitive_wrapper_class para encontrar la clase contenedora de un tipo primivito.

Nhat Dinh
fuente
8

Intentaré hacerte entender con la ayuda de un ejemplo. Suponga que tiene una tabla relacional (ESTUDIANTE) con dos columnas e ID (int) y NAME (String). Ahora, como ORM, habría creado una clase de entidad similar a la siguiente:

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

}

Supongamos que la tabla ya tenía entradas. Ahora, si alguien te pregunta, agrega otra columna de "EDAD" (int)

ALTER TABLE ESTUDIANTE AÑADIR EDAD int NULL

Deberá establecer los valores predeterminados como NULL para agregar otra columna en una tabla precargada. Esto te hace agregar otro campo en la clase. Ahora surge la pregunta de si utilizará un tipo de datos primitivo o un tipo de datos contenedor no primitivo para declarar el campo.

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

o

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

tendrá que declarar el campo como un tipo de datos contenedor no primitivo porque el contenedor intentará mapear la tabla con la entidad. Por lo tanto, no podría mapear valores NULL (predeterminado) si no declara el campo como envoltorio y eventualmente arrojaría "Se asignó un valor nulo a una propiedad del establecedor de tipo primitivo" Excepción.

codechefvaibhavkashyap
fuente
6

use Integer como tipo y proporcione setter / getter en consecuencia.

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...
arn-arn
fuente
4

No use primitivas en sus clases de Entidad , use en su lugar sus respectivos envoltorios. Eso solucionará este problema.

Fuera de sus clases de Entidad, puede usar la validación! = Null para el resto de su flujo de código.

Israelm
fuente
3

Evite completamente nullen DB via NOT NULLy en la entidad Hibernate via en @Column(nullable = false)consecuencia o use el Longcontenedor en lugar de sus longprimitivas.

Una primitiva no es un Objeto, por lo tanto, no se puede asignarle null.

am0wa
fuente
3

Hay dos caminos

  • Asegúrese de que la columna db no esté permitida null
  • Las clases de User Wrapper para la variable de tipo primitivo como private int var;se pueden inicializar comoprivate Integer var;
4302836
fuente
2

@Dinh Nhat, su método de establecimiento se ve mal porque puso un tipo primitivo allí nuevamente y debería ser:

public void setClient_os_id(Integer clientOsId) {
client_os_id = clientOsId;
}
Kamiel Ahmadpour
fuente
2

Cambie el tipo de parámetro de primitivo a Object y ponga una marca nula en el setter. Ver ejemplo a continuación

public void setPhoneNumber(Long phoneNumber) {
    if (phoneNumber != null)
        this.phoneNumber = phoneNumber;
    else
        this.extension = 0l;
}
Sandeep Shankar Harikrishnan
fuente
2
@Column(name ="LEAD_ID")
private int leadId; 

Cambiar a

@Column(name ="LEAD_ID")
private Integer leadId; 
Rakesh Yadav
fuente
1

Asegúrese de que el campo myAttribute de su base de datos contenga un valor nulo en lugar de cero.

Aravinthan K
fuente