Чому я отримую повідомлення про помилку “Нульове значення присвоєно властивості примітивного типу сеттера” під час використання HibernateCriteriaBuilder у Grails


100

Я отримую таку помилку при використанні примітивного атрибута в моєму об'єкті домену 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)

не псуйте свої дані і вам не доведеться використовувати непримітивні обгортки. Я пропустив ввести деякі значення, і мені вдалося виправити цю помилку, додавши її до бази даних.
Goot

Відповіді:


168

Відповідно до цієї нитки SO , рішення полягає у використанні непомітивних типів обгортки; наприклад, Integerзамість int.


6
Усі послуги Codehaus були припинені.
Priyanshu Chauhan

46

Нульове значення не може бути призначене примітивному типу, наприклад, int, long, boolean тощо. Якщо стовпець бази даних, який відповідає полі у вашому об'єкті, може бути нульовим, то ваше поле повинно бути класом обгортки, як Integer, Long, Булева та ін.

Небезпека полягає в тому, що ваш код буде працювати нормально, якщо в БД немає нульових значень, але вийде з ладу, коли нули будуть вставлені.

І ви завжди можете повернути примітивний тип від геттера. Наприклад:

  private Integer num;

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

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

Але в більшості випадків ви захочете повернути клас обгортки.

Тому або встановіть свій стовпець БД таким, що не дозволяє нулю, або використовуйте клас обгортки.


13

Примітивний тип не може бути нульовим. Таким чином, рішення замінить примітивний тип на примітивний клас обгортки у вашому файлі tableName.java. Як от:

@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 для пошуку класу обгортки типу примітиву.


8

Я спробую змусити вас зрозуміти за допомогою прикладу. Припустимо, у вас була реляційна таблиця (STUDENT) з двома стовпцями та ідентифікаторами (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;
    }

}

Давайте припустимо, що таблиця вже мала записи. Тепер, якщо хтось попросить вас додати ще один стовпець "AGE" (int)

АЛЬТЕР СТУДЕНТ СТОЛОК ДОДАТИ ВІРНІСТЬ in NULL

Вам доведеться встановити значення за замовчуванням як NULL, щоб додати ще один стовпець у попередньо заповнену таблицю. Це змушує вас додати ще одне поле у ​​класі. Тепер виникає питання, чи використовуватимете ви примітивний тип даних або непримітивний тип даних для обгортки для оголошення поля.

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

або

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

вам доведеться оголосити поле непримітивним типом даних для обгортки, оскільки контейнер буде намагатися зіставити таблицю з сутністю. Таким чином, він не зможе відобразити значення NULL (за замовчуванням), якщо ви не оголосите поле оберткою і в кінцевому підсумку викинете "Null value було присвоєно властивості примітивної задачі типу" Виняток.


6

використовуйте Integer як тип та надайте сетеру / getter відповідно.

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...

4

Не використовуйте примітивів у своїх курсах Entity , використовуйте замість них їх обгортки. Це вирішить цю проблему.

Із класів Entity ви можете використовувати перевірку! = Null для решти потоку коду.


3

Або повністю уникайте nullв БД через NOT NULLі в сплячому об'єкті @Column(nullable = false)відповідно або використовуйте Longобгортку замість longпримітивів.

Примітив не є Об'єктом, тому ви не можете його призначити null.


3

Є два способи

  • Переконайтеся, що колона db не дозволена null
  • Класи User Wrapper для змінної примітивного типу типу private int var;можуть бути ініціалізовані якprivate Integer var;

2

@Dinh Nhat, ваш метод сетера виглядає неправильним, оскільки ви знову поміщаєте примітивний тип, і він повинен бути:

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

2

Змініть тип параметра з примітивного на Object і поставте нульову перевірку в сеттер. Дивіться приклад нижче

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.