เหตุใดฉันจึงได้รับข้อความแสดงข้อผิดพลาด“ ค่า Null ถูกกำหนดให้กับคุณสมบัติของตัวตั้งค่าประเภทดั้งเดิมของ” เมื่อใช้ HibernateCriteriaBuilder ใน Grails


101

ฉันได้รับข้อผิดพลาดต่อไปนี้เมื่อใช้แอตทริบิวต์ดั้งเดิมในวัตถุโดเมน 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)

อย่าทำให้การป้อนข้อมูลของคุณยุ่งเหยิงและคุณจะไม่ต้องใช้ Wrapper ที่ไม่ใช่แบบดั้งเดิม ฉันพลาดที่จะป้อนค่าบางค่าและฉันสามารถแก้ไขข้อผิดพลาดนี้ได้โดยเพิ่มลงในฐานข้อมูล
Goot

คำตอบ:



48

ไม่สามารถกำหนดค่า null ให้กับประเภทดั้งเดิมเช่น int, long, boolean เป็นต้นหากคอลัมน์ฐานข้อมูลที่ตรงกับฟิลด์ในออบเจ็กต์ของคุณเป็นค่าว่างฟิลด์ของคุณควรเป็นคลาส wrapper เช่น Integer, Long บูลีน ฯลฯ

อันตรายคือโค้ดของคุณจะทำงานได้ดีหากไม่มี null ใน DB แต่จะล้มเหลวเมื่อใส่ null

และคุณสามารถคืนค่าประเภทดั้งเดิมจาก getter ได้ตลอดเวลา เช่น:

  private Integer num;

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

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

แต่ในกรณีส่วนใหญ่คุณจะต้องการส่งคืนคลาส Wrapper

ดังนั้นตั้งค่าคอลัมน์ DB ของคุณเพื่อไม่ให้มีค่าว่างหรือใช้คลาส wrapper


13

ประเภทดั้งเดิมต้องไม่เป็นโมฆะ ดังนั้นวิธีแก้ปัญหาคือแทนที่ primitive type ด้วยคลาส primitive wrapper ในไฟล์ 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เพื่อค้นหาคลาส wrapper ของประเภท primivite


8

ฉันจะพยายามทำให้คุณเข้าใจด้วยความช่วยเหลือของตัวอย่าง สมมติว่าคุณมีตารางเชิงสัมพันธ์ (STUDENT) ที่มีสองคอลัมน์และ ID (int) และ NAME (สตริง) ตอนนี้ในฐานะ 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) อีกคอลัมน์

แก้ไขตารางนักเรียนเพิ่มอายุ int เป็นโมฆะ

คุณจะต้องตั้งค่าเริ่มต้นเป็น NULL เพื่อเพิ่มคอลัมน์อื่นในตารางที่เติมไว้ล่วงหน้า ทำให้คุณเพิ่มเขตข้อมูลอื่นในชั้นเรียน ตอนนี้คำถามเกิดขึ้นว่าคุณจะใช้ประเภทข้อมูลดั้งเดิมหรือชนิดข้อมูลที่ไม่ใช่แบบดั้งเดิมสำหรับการประกาศฟิลด์

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

หรือ

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

คุณจะต้องประกาศเขตข้อมูลเป็นชนิดข้อมูลที่ไม่ใช่แบบดั้งเดิมของ wrapper เนื่องจากคอนเทนเนอร์จะพยายามแมปตารางกับเอนทิตี ดังนั้นจึงไม่สามารถแมปค่า NULL (ค่าเริ่มต้น) ได้หากคุณไม่ประกาศฟิลด์เป็น wrapper และในที่สุดก็จะโยน "ค่า Null ถูกกำหนดให้กับคุณสมบัติของตัวตั้งค่าประเภทดั้งเดิม"


6

ใช้ Integer เป็นประเภทและระบุ setter / getter ตาม ..

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...

4

อย่าใช้แบบดั้งเดิมในคลาสเอนทิตีของคุณใช้แทน wrapper ตามลำดับ ที่จะแก้ไขปัญหานี้

จากคลาสเอนทิตีของคุณคุณสามารถใช้การตรวจสอบความถูกต้อง! = null สำหรับโฟลว์โค้ดที่เหลือของคุณ


3

หลีกเลี่ยงอย่างเต็มที่nullใน DB ผ่านNOT NULLและในเอนทิตีไฮเบอร์เนตผ่าน@Column(nullable = false)ตามนั้นหรือใช้Longwrapper แทนการใช้งานlongแบบดั้งเดิม

ดั้งเดิมไม่ใช่วัตถุดังนั้นคุณจึงไม่สามารถกำหนดให้nullกับมันได้


3

มีสองทาง

  • ตรวจสอบให้แน่ใจว่าไม่อนุญาตให้ใช้คอลัมน์ db null
  • คลาส 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;
}


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.