Java 互相關(guān)聯(lián)的實(shí)體無限遞歸問題的解決
Java 互相關(guān)聯(lián)的實(shí)體無限遞歸
今天在測(cè)試的時(shí)候出現(xiàn)了一個(gè)bug,在把關(guān)聯(lián)實(shí)體序列化返回的過程中報(bào)錯(cuò)了,提示
Caused by: java.lang.StackOverflowError: null
這個(gè)是堆棧溢出錯(cuò)誤,根據(jù)錯(cuò)誤線索查找,最后發(fā)現(xiàn)Column和Table實(shí)體互相關(guān)聯(lián),也就是說
Column實(shí)體中有Table屬性,Table實(shí)體中也有Column屬性,導(dǎo)致了在序列化的過程中出現(xiàn)了死循環(huán),無限遞歸,以至堆棧溢出報(bào)錯(cuò)。
在Jackson2.0以前的解決辦法是
在關(guān)聯(lián)的屬性上添加
@JsonBackReference
或者
@JsonIgnore
注解中的一個(gè)即可。但是從Jackson2.0以后的版本開始,提供@JsonIdentityInfo注解實(shí)現(xiàn)這個(gè)問題的解決,在實(shí)體類前加注解
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
好好理解Java中的遞歸
遞歸的思想
把規(guī)模大的問題轉(zhuǎn)化為規(guī)模小的相似的子問題來解決。在函數(shù)實(shí)現(xiàn)時(shí),因?yàn)榻鉀Q大問題的方法和解決小問題的方法往往是同一個(gè)方法,所以就產(chǎn)生了函數(shù)調(diào)用它自身的情況。另外這個(gè)解決問題的函數(shù)必須有明顯的結(jié)束條件,這樣就不會(huì)產(chǎn)生無限遞歸的情況了。
一句話總結(jié):遞歸就是自己調(diào)用自己。
遞歸的條件要素
1、遞歸有兩個(gè)重要條件
- 可以通過遞歸調(diào)用來縮小問題規(guī)模,且新問題與原問題有著相同的形式。(自身調(diào)用)
- 存在一種簡單情境,可以使遞歸在簡單情境下退出。(遞歸出口)
2、遞歸的三要素
- 嘗試將一個(gè)問題化簡到更小的規(guī)模
- 父問題與子問題不能有重疊的部分
- 一定有一種可以退出程序的情況
遞歸的算法結(jié)構(gòu)
遞歸的常用算法偽代碼如下:
func( mode){ if(endCondition){ //遞歸出口 end; }else{ func(mode_small) //調(diào)用本身,遞歸 } }
遞歸實(shí)戰(zhàn)舉例
遞歸講起來還是有點(diǎn)小抽象,我們直接來看代碼
1、斐波那契數(shù)的遞歸實(shí)現(xiàn)
斐波那契數(shù)列的遞推公式:Fib(n)=Fib(n-1)+Fib(n-2),生成數(shù)列(1、1、2、3、5、8...)。
public static int fib(int n) throws Exception { if (n < 0){ throw new Exception("請(qǐng)輸入正確的參數(shù)"); } else if (n == 0 || n == 1){ return n; } else { return fib(n - 1) + fib(n - 2); // 調(diào)用自己 } }
2、99乘法表的遞歸實(shí)現(xiàn)
public static void mul(int n){ if(n==1){ System.out.println("1*1=1"); }else { mul(n -1); for(int i=1;i<=n;i++){ System.out.println(i + "*" + n + "=" + i*n + " "); } } }
小結(jié)一下吧
遞歸算法是一種直接或間接地調(diào)用自身的算法。如果一個(gè)問題可以解可以分解為幾個(gè)子問題的解; 這個(gè)問題與分解之后的子問題,除了數(shù)據(jù)規(guī)模不同,求解思路完全一樣;并且存在明顯的遞歸終止條件;那么遞歸將是一種不錯(cuò)的選擇。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
BMIDE環(huán)境導(dǎo)入項(xiàng)目報(bào)編碼錯(cuò)誤解決方案
這篇文章主要介紹了BMIDE環(huán)境導(dǎo)入項(xiàng)目報(bào)編碼錯(cuò)誤解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法
這篇文章主要介紹了Spring異常實(shí)現(xiàn)統(tǒng)一處理的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12Java使用IO流實(shí)現(xiàn)音頻的剪切和拼接
這篇文章主要為大家詳細(xì)介紹了Java使用IO流實(shí)現(xiàn)音頻的剪切和拼接,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決
本文主要介紹了Springboot視頻接口報(bào)大量的ClientAbortException找不到原因的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08SpringBoot整合SSO(single sign on)單點(diǎn)登錄
這篇文章主要介紹了SpringBoot整合SSO(single sign on)單點(diǎn)登錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06java后端實(shí)現(xiàn)信息分頁查詢的示例代碼
在一個(gè)頁面展示大量的用戶信息不便于觀看,因此就需要采用分頁展示的方法,本文就來為大家介紹一下java后端如何實(shí)現(xiàn)信息分頁查詢,需要的小伙伴可以參考下2023-11-11java調(diào)用opencv身份證號(hào)識(shí)別詳解
這篇文章主要為大家詳細(xì)介紹了java如何調(diào)用opencv實(shí)現(xiàn)身份證號(hào)的識(shí)別,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03