Por que recebo a mensagem de erro “Valor nulo atribuído a uma propriedade do setter de tipo primitivo de” ao usar HibernateCriteriaBuilder em Grails

100

Recebo o seguinte erro ao usar um atributo primitivo em meu objeto de domínio 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)
Peter
fonte
não bagunce sua entrada de dados e você não terá que usar wrappers não primitivos. Esqueci de inserir alguns valores e consegui corrigir esse erro adicionando-o ao banco de dados.
Goot

Respostas:

168

De acordo com este segmento SO , a solução é usar os tipos de invólucro não primitivos; por exemplo, em Integervez de int.

Peter
fonte
6
Todos os serviços da Codehaus foram encerrados.
Priyanshu Chauhan
46

Um valor nulo não pode ser atribuído a um tipo primitivo, como int, longo, booleano, etc. Se a coluna do banco de dados que corresponde ao campo em seu objeto pode ser nula, então seu campo deve ser uma classe de invólucro, como Inteiro, Longo, Booleano, etc.

O perigo é que seu código funcionará bem se não houver nulos no banco de dados, mas falhará quando os nulos forem inseridos.

E você sempre pode retornar o tipo primitivo do getter. Ex:

  private Integer num;

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

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

Mas na maioria dos casos, você desejará retornar a classe de wrapper.

Portanto, defina sua coluna DB para não permitir nulos ou use uma classe de invólucro.

MattC
fonte
13

Um tipo primitivo não pode ser nulo. Portanto, a solução é substituir o tipo primitivo pela classe de wrapper primitiva em seu arquivo tableName.java. Tal 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 a classe de invólucro de um tipo primivito.

Nhat Dinh
fonte
8

Vou tentar fazer você entender com a ajuda de um exemplo. Suponha que você tenha uma tabela relacional (STUDENT) com duas colunas e ID (int) e NAME (String). Agora, como ORM, você teria feito uma classe de entidade mais ou menos como a seguinte: -

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

}

Vamos supor que a tabela já tenha entradas. Agora, se alguém pedir para você adicionar outra coluna de "AGE" (int)

ALTER TABLE STUDENT ADD AGE int NULL

Você terá que definir os valores padrão como NULL para adicionar outra coluna em uma tabela pré-preenchida. Isso faz com que você adicione outro campo na classe. Agora surge a pergunta se você usará um tipo de dados primitivo ou um tipo de dados wrapper não primitivo para declarar o campo.

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

ou

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

você terá que declarar o campo como tipo de dados de wrapper não primitivo porque o contêiner tentará mapear a tabela com a entidade. Conseqüentemente, ele não seria capaz de mapear valores NULL (padrão) se você não declarasse o campo como wrapper e eventualmente emitisse "Valor nulo atribuído a uma propriedade do setter de tipo primitivo" Exceção.

codechefvaibhavkashyap
fonte
6

use Integer como o tipo e forneça setter / getter de acordo.

private Integer num;

public Integer getNum()...

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

Não use primitivas em suas classes de Entidade , use seus respectivos invólucros. Isso vai resolver o problema.

Fora de suas classes de entidade, você pode usar a validação! = Null para o resto do seu fluxo de código.

Israelita
fonte
3

Evite totalmente nullno DB via NOT NULLe na entidade do Hibernate via @Column(nullable = false)ou use Longwrapper ao invés de seus longprimitivos.

Um primitivo não é um objeto, portanto, você não pode atribuí null-lo.

am0wa
fonte
3

Existem duas maneiras

  • Certifique-se de que a coluna db não é permitida null
  • Classes de Wrapper de usuário para a variável de tipo primitivo como private int var;podem ser inicializadas comoprivate Integer var;
4302836
fonte
2

@Dinh Nhat, seu método setter parece errado porque você colocou um tipo primitivo lá novamente e deveria ser:

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

Altere o tipo de parâmetro de primitivo para Object e coloque uma verificação nula no setter. Veja o exemplo abaixo

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

Mudar para

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

Certifique-se de que o campo myAttribute do seu banco de dados contém nulo em vez de zero.

Aravinthan K
fonte