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
你可以看到在編譯和運行時期,將null強制轉換成任何引用類型都是可行的,在運行時期都不會拋出空指針異常。

4)null可以賦值給引用變量,但不能將null賦給基本類型變量,例如int、double、float、boolean。編譯器將會報錯。

正如你看到的那樣,當你直接將null賦值給基本類型,會出現編譯錯誤。但是如果將null賦值給包裝類object,然后將object賦給各自的基本類型,編譯器不會報,但是你將會在運行時期遇到空指針異常。這是Java中的自動拆箱導致的。

5) 任何含有null值的包裝類在Java拆箱生成基本數據類型時候都會拋出一個空指針異常。一些程序員犯這樣的錯誤,他們認為自動裝箱會將null轉換成各自基本類型的默認值,例如對於int轉換成0,布爾類型轉換成false,但是那是不正確的,如下面所示:

Integer iAmNull =  null ;
int  i = iAmNull;  // Remember - No Compilation Error
 
但是當你運行上面的代碼片段的時候,你會在控制台上看到主線程拋出空指針異常。在使用HashMap和Integer鍵值的時候會發生很多這樣的錯誤。當你運行下面代碼的時候就會出現錯誤。
public class Test3 {
  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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM