Spring Data jpa findBy的使用和null值探索
近期在调用jpa框架中findById()进行查找对象时出现了Null value was assigned to a property of...错误,简单来说就是null被赋予给某个属性出错,当时以为是属性没赋予值出了错误,因为当我在mysql表记录中插入相应值后,运行遍通过了,但后来网上搜索错误后发现是数据类型不一致才导致这个错误,研究代码和表类型的时候发现那两个报错的属性都是int型的数据,而没有任何地方说明需要填充值,我就思考自己的想法出现了错误,把错误上网搜索后我终于发现一切都是null值的原因。
jpa中findBy函数查询结果一定是整个对象的所有字段,想要某个字段,只能用List接受整个结果再去get(i)找到想要查找的字段,意思就是如果是User findById(),那么返回的就是这个对应User的所有字段,关于[jpa]findBy的使用请跳转
https://blog.csdn.net/changningbuddha/article/details/77987236
所以当需要返回所有字段就出错了,因为有两个int类型的属性填入的值是null值(mysql中int类型的设置的默认值是null),那么null到底是什么,为什么其他许多类型赋予null不会报错,而int型就出错了。
null是Java中一个很重要的概念。null设计初衷是为了表示一些缺失的东西,例如缺失的用户、资源或其他东西。但是,后来实际使用时令人头疼的空指针异常给Java程序员带来不少的骚扰。下面是Java中null关键字的基本细节,并且探索一些技术来尽可能的减少null的检查以及如何避免恶心的空指针异常。
1)首先,null是关键字,像public、static、final。它是大小写敏感的,你不能将null写成Null或NULL,编译器将不能识别它们然后报错。
2)就像每种基本类型都有默认值一样,如int默认值为0,boolean的默认值为false,null是任何引用类型的默认值,不严格的说是所有object类型的默认值。就像你创建了一个布尔类型的变量,它将false作为自己的默认值,Java中的任何引用变量都将null作为默认值。这对所有变量都是适用的,如成员变量、局部变量、实例变量、静态变量(但当你使用一个没有初始化的局部变量,编译器会警告你)。为了证明这个事实,你可以通过创建一个变量然后打印它的值来观察这个引用变量。
3)我们要澄清一些误解,null既不是对象也不是一种类型,它仅是一种特殊的值,你可以将其赋予任何引用类型,你也可以将null转化成任何类型,来看下面的代码:
String str =
null
;
Integer i =
null
;
Double d =
null
;
String myStr = (String)
null
;
Integer myI = (Integer)
null
;
Double myD = (Double)
null
;
4)null可以赋值给引用变量,但不能将null赋给基本类型变量,例如int、double、float、boolean。编译器将会报错。
5) 任何含有null值的包装类在Java拆箱生成基本数据类型时候都会抛出一个空指针异常。一些程序员犯这样的错误,他们认为自动装箱会将null转换成各自基本类型的默认值,例如对于int转换成0,布尔类型转换成false,但是那是不正确的,如下面所示:
Integer iAmNull =
null
;
int
i = iAmNull;
// Remember - No Compilation Error
public static void main(String args[]) throws InterruptedException { Map numberAndCount = new HashMap<>(); int[] numbers = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5}; for(int i : numbers){
int count = (int) numberAndCount.get(i);//NullPointerException numberAndCount.put(i, count++); } } }
package test;
import java.util.HashMap;
import java.util.Map;
public class Test3 {
public static void main(String args[]) throws InterruptedException {
Map numberAndCount = new HashMap<>();
Integer[] numbers = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5};
for(Integer i : numbers){
Integer count = (Integer) numberAndCount.get(i);
numberAndCount.put(i, count++); // NullPointerException
}
}
}
这段代码看起来非常简单并且没有错误。你所做的一切是找到一个数字在数组中出现了多少次,这是Java数组中典型的寻找重复的技术。开发者首先得到以前的数值,然后再加一,最后把值放回Map里。程序员可能会以为,调用put方法时,第一种方式是转换int报空指针,验证之前说的。第二种方式,自动装箱会自己处理好拆装箱问题,但是忘记了当一个数字没有计数值的时候,get方法返回null,而不是0,因为Integer的默认值是null而不是0。当把null值传递给一个int型变量的时候自动装箱将会返回空指针异常。
引用了这么多,如何避免空指针异常和null值赋予出现的编译错误,重点来说就是理解null值的正确用法,在方法引用时多加几层防护措施,例如在给int类型set或get的时候进行如if( int i>=0)的判定或者在没有给int型赋值时给予默认值0或者在数据库表中设置默认值0。
参考资料:
http://www.importnew.com/14229.html
https://blog.csdn.net/chenyuangege/article/details/50180313