Pourquoi est-ce que j'obtiens un message d'erreur «Une valeur nulle a été assignée à une propriété du setter de type primitif de» lorsque j'utilise HibernateCriteriaBuilder dans Grails


100

J'obtiens l'erreur suivante lors de l'utilisation d'un attribut primitif dans mon objet de domaine 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)

ne gâchez pas votre entrée de données et vous n'aurez pas à utiliser des wrappers non primitifs. J'ai manqué d'entrer certaines valeurs et j'ai réussi à corriger cette erreur en l'ajoutant à la base de données.
Goot

Réponses:


168

Selon ce thread SO , la solution est d'utiliser les types de wrapper non primitifs; par exemple, Integerau lieu de int.


6
Tous les services Codehaus ont été résiliés.
Priyanshu Chauhan

46

Une valeur nulle ne peut pas être affectée à un type primitif, comme int, long, boolean, etc. Si la colonne de base de données qui correspond au champ de votre objet peut être nulle, alors votre champ doit être une classe wrapper, comme Integer, Long, Booléen, etc.

Le danger est que votre code fonctionnera correctement s'il n'y a pas de valeurs nulles dans la base de données, mais échouera une fois les valeurs nulles insérées.

Et vous pouvez toujours renvoyer le type primitif depuis le getter. Ex:

  private Integer num;

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

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

Mais dans la plupart des cas, vous souhaiterez renvoyer la classe wrapper.

Donc, définissez votre colonne DB pour ne pas autoriser les valeurs nulles ou utilisez une classe wrapper.


13

Un type primitif ne peut pas être nul. La solution consiste donc à remplacer le type primitif par la classe d'encapsulation primitive dans votre fichier tableName.java. Tel que:

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

référence http://en.wikipedia.org/wiki/Primitive_wrapper_class pour trouver la classe wrapper d'un type primitif.


8

Je vais essayer de vous faire comprendre à l'aide d'un exemple. Supposons que vous ayez une table relationnelle (STUDENT) avec deux colonnes et ID (int) et NAME (String). Maintenant, en tant que ORM, vous auriez créé une classe d'entité un peu comme suit: -

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

}

Supposons que la table ait déjà des entrées. Maintenant, si quelqu'un vous demande d'ajouter une autre colonne de "AGE" (int)

ALTER TABLE ETUDIANT AJOUTER AGE int NULL

Vous devrez définir les valeurs par défaut comme NULL pour ajouter une autre colonne dans un tableau pré-rempli. Cela vous oblige à ajouter un autre champ dans la classe. La question se pose maintenant de savoir si vous utiliserez un type de données primitif ou un type de données wrapper non primitif pour déclarer le champ.

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

ou

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

vous devrez déclarer le champ comme type de données wrapper non primitif car le conteneur essaiera de mapper la table avec l'entité. Par conséquent, il ne serait pas en mesure de mapper les valeurs NULL (par défaut) si vous ne déclarez pas le champ comme wrapper et lèverait éventuellement une exception "La valeur Null a été affectée à une propriété du setter de type primitif".


6

utilisez Integer comme type et fournissez setter / getter en conséquence.

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...

4

N'utilisez pas de primitives dans vos classes Entity , utilisez plutôt leurs wrappers respectifs. Cela résoudra ce problème.

À partir de vos classes Entity, vous pouvez utiliser la validation! = Null pour le reste de votre flux de code.


3

Soit éviter complètement nulldans DB via NOT NULLet dans l'entité Hibernate via en @Column(nullable = false)conséquence ou utiliser Longwrapper à la place de vos longprimitives.

Une primitive n'est pas un objet, donc vous ne pouvez pas lui assigner null.


3

Il y a deux façons

  • Assurez-vous que la colonne db n'est pas autorisée null
  • Les classes User Wrapper pour la variable de type primitif comme private int var;peuvent être initialisées commeprivate Integer var;

2

@Dinh Nhat, votre méthode setter semble incorrecte car vous y mettez à nouveau un type primitif et cela devrait être:

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

2

Changez le type de paramètre de primitif à Object et mettez une vérification nulle dans le setter. Voir l'exemple ci-dessous

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

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

Changer pour

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

1

Assurez-vous que le champ myAttribute de votre base de données contient null au lieu de zéro.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.