调用页面大小大于 36 的 Spring Data MongoDB 存储库方法时发生 StackOverflowError

StackOverflowError when calling Spring Data MongoDB repository method with a page size bigger than 36

我在调用 MongoDB 存储库接口的方法时收到 WhosebugError:

public interface TermRepository extends MongoRepository<Term, String>, QuerydslPredicateExecutor<Term> {
    // [...]
    @Query("{$or:[{'apis' : {$in : ?0 } }, {$text:{$search:?1}}]}")
    Page<Term> globalSearch(List<DBRef> apis, String searchKeyword, Pageable pageable);
}
{
    $or: [{
        'apis': {
            $in: [{
                '$ref': 'api',
                '$id': ObjectId('5e3ad9faaafa595898b6a682')
            }]
        }
    }, {
        $text: {
            $search: 'account'
        }
    }]
}

有人知道发生了什么事吗?

学期:

public class Term {

    @Id
    private String id;

    @NotBlank
    @TextIndexed
    @JsonProperty
    private String name;

    @NotBlank
    @TextIndexed
    @JsonProperty
    private String objectType;

    @Transient
    @JsonProperty
    private String snakeCase;

    @NotEmpty
    @JsonProperty
    private List<String> functionalCategories;

    @NotNull
    @JsonProperty
    private TermTypeEnum termType;

    @NotEmpty
    @JsonProperty
    private Map<String, String> description;

    @Setter
    @NotNull
    @JsonProperty
    private TermStateEnum state;

    @NotBlank
    @TextIndexed
    @JsonProperty
    private String example;

    @DBRef
    @NotNull
    @Indexed
    @JsonProperty
    private List<Api> apis;

    @DBRef
    @NotNull
    @JsonProperty
    private User contributor;

    @NotBlank
    @TextIndexed
    @JsonProperty
    private String version;

    @DBRef
    @JsonProperty
    private Map<String, Term> attributes;
}

堆栈跟踪:https://pastebin.com/y0XYt7p6

尽管可能存在循环引用,因为 Term 具有属性 Map,但我认为产生堆栈溢出的不是循环引用。

做一些调试,我看到发生堆栈溢出,因为最后spring-data 只实例化这个 Term(不是其他的,所以我没有看到循环引用):

Term(id=5e3ad9faaafa595898b6a7ea, name=debitCurrency, objectType=string, snakeCase=debit_currency, functionalCategories=null, termType=BODY, description={"english"=Debit Currency.}, state=PROPOSED, example=null, apis=[Api(id=5e3ad9faaafa595898b6a67f, name=Payments-1.0.1, description=null, responsible=null)], contributor=null, version=null, attributes=null)

这又不引用其他术语。

这是另一个Term,只是为了比较:

Term(id=5e3ad9faaafa595898b6a6c8, name=displayCardNumber, objectType=string, snakeCase=display_card_number, functionalCategories=null, termType=BODY, description={"english"=Related card number to the account.}, state=PROPOSED, example=null, apis=[Api(id=5e3ad9faaafa595898b6a682, name=Accounts-1.0.2, description=null, responsible=null)], contributor=null, version=null, attributes=null)

我看不出有什么区别,但是 debitCurrency 会产生堆栈溢出而 displayCardNumber 不会。

我确实有一个循环引用(更准确地说是自我引用)。

我想出了一个解决方法,包括制作 @DBRef 属性 lazy=true,并实现 class Term 的自定义序列化程序,至极具有自引用(或循环引用)。实现自定义序列化程序的原因是,我可以保存一组已经序列化的对象,如果我必须再次序列化一个对象,我只是不这样做。