Tại sao tôi nhận được thông báo lỗi “Giá trị Null được gán cho thuộc tính của bộ định dạng nguyên thủy của” khi sử dụng HibernateCriteriaBuilder trong Grails


100

Tôi gặp lỗi sau khi sử dụng thuộc tính nguyên thủy trong đối tượng miền grails của mình:

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)

không làm rối tung quá trình nhập dữ liệu của bạn và bạn sẽ không phải sử dụng các trình bao bọc không nguyên thủy. Tôi đã lỡ nhập một số giá trị và tôi đã sửa được lỗi này bằng cách thêm nó vào cơ sở dữ liệu.
Goot

Câu trả lời:


168

Theo chủ đề SO này , giải pháp là sử dụng các loại trình bao bọc không nguyên thủy; ví dụ, Integerthay vì int.


6
Tất cả các dịch vụ của Codehaus đã bị chấm dứt.
Priyanshu Chauhan

46

Giá trị null không thể được gán cho kiểu nguyên thủy, như int, long, boolean, v.v. Nếu cột cơ sở dữ liệu tương ứng với trường trong đối tượng của bạn có thể là null, thì trường của bạn phải là một lớp wrapper, như Integer, Long, Boolean, v.v.

Điều nguy hiểm là mã của bạn sẽ chạy tốt nếu không có null trong DB, nhưng sẽ không thành công khi các null được chèn vào.

Và bạn luôn có thể trả về kiểu nguyên thủy từ getter. Ví dụ:

  private Integer num;

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

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

Nhưng trong hầu hết các trường hợp, bạn sẽ muốn trả lại lớp wrapper.

Vì vậy, hãy đặt cột DB của bạn thành không cho phép null hoặc sử dụng một lớp trình bao bọc.


13

Một kiểu nguyên thủy không được rỗng. Vì vậy, giải pháp là thay thế kiểu nguyên thủy bằng lớp bao bọc nguyên thủy trong tệp tableName.java của bạn. Nhu la:

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

tham khảo http://en.wikipedia.org/wiki/Primitive_wrapper_class để tìm lớp wrapper của loại primivite.


8

Tôi sẽ cố gắng làm cho bạn hiểu với sự trợ giúp của một ví dụ. Giả sử bạn có một bảng quan hệ (STUDENT) với hai cột và ID (int) và NAME (String). Bây giờ là ORM, bạn sẽ tạo một lớp thực thể giống như sau: -

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

}

Giả sử bảng đã có mục nhập. Bây giờ nếu ai đó yêu cầu bạn thêm một cột khác của "AGE" (int)

BẢNG ALTER SINH VIÊN THÊM TUỔI int NULL

Bạn sẽ phải đặt các giá trị mặc định là NULL để thêm một cột khác vào bảng được điền trước. Điều này làm cho bạn thêm một trường khác trong lớp. Bây giờ câu hỏi đặt ra là bạn sẽ sử dụng kiểu dữ liệu nguyên thủy hay kiểu dữ liệu trình bao bọc không nguyên thủy để khai báo trường.

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

hoặc là

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

bạn sẽ phải khai báo trường là kiểu dữ liệu trình bao bọc không nguyên thủy vì vùng chứa sẽ cố gắng ánh xạ bảng với thực thể. Do đó, nó sẽ không thể ánh xạ các giá trị NULL (mặc định) nếu bạn không khai báo trường dưới dạng trình bao bọc và cuối cùng sẽ ném "Giá trị Null đã được gán cho một thuộc tính của setter kiểu nguyên thủy" Ngoại lệ.


6

sử dụng Integer làm loại và cung cấp setter / getter cho phù hợp ..

private Integer num;

public Integer getNum()...

public void setNum(Integer num)...

4

Không sử dụng các nguyên mẫu trong các lớp Thực thể của bạn , thay vào đó hãy sử dụng các trình bao bọc tương ứng của chúng. Điều đó sẽ khắc phục sự cố này.

Ngoài các lớp Thực thể của bạn, bạn có thể sử dụng xác thực! = Null cho phần còn lại của luồng mã của bạn.


3

Hoặc tránh hoàn toàn nulltrong DB qua NOT NULLvà trong thực thể Hibernate thông qua @Column(nullable = false)tương ứng hoặc sử dụng Longtrình bao bọc thay vì bạn longnguyên thủy.

Một nguyên thủy không phải là một Đối tượng, do đó bạn không thể gán nullcho nó.


3

Có hai cách

  • Đảm bảo rằng cột db không được phép null
  • Các lớp User Wrapper cho biến kiểu nguyên thủy như private int var;có thể được khởi tạo nhưprivate Integer var;

2

@Dinh Nhat, phương thức setter của bạn có vẻ sai vì bạn lại đặt một kiểu nguyên thủy vào đó và nó phải là:

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

2

Thay đổi kiểu tham số từ nguyên thủy thành Đối tượng và kiểm tra null trong setter. Xem ví dụ bên dưới

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

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

Thay đổi thành

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

1

Đảm bảo trường myAttribute trong cơ sở dữ liệu của bạn chứa null thay vì 0.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.