StackOverflowError при вызове метода репозитория Spring Data MongoDB с размером страницы более 36 - PullRequest
2 голосов
/ 05 февраля 2020

Я получаю StackOverflowError при вызове метода моего интерфейса хранилища MongoDB:

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);
}
  • apis - это список только с одним DBRef: new DBRef ("api" , новый ObjectId ("5e3ad9faaafa595898b6a682"))

  • searchKeyword равен "account"

  • pageable равен Page request [number: 0, size 37, sort: UNSORTED]. Если size равно 36, он не выдает ошибку StackOverflowError!
  • Запрос переводится в
{
    $or: [{
        'apis': {
            $in: [{
                '$ref': 'api',
                '$id': ObjectId('5e3ad9faaafa595898b6a682')
            }]
        }
    }, {
        $text: {
            $search: 'account'
        }
    }]
}
  • Если я выполняю запрос непосредственно в mon go, он возвращает 55 элементов.
  • Я пытался увеличить стек потоков до -Xss1G (это много, я знаю), и он просто медленно заполняет стек и не возвращается. Если я перезапущу тест с размером страницы 36, он сразу же вернется.

Кто-нибудь знает, что происходит?

Термин:

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

Stacktrace: https://pastebin.com/y0XYt7p6

Хотя может существовать циклическая ссылка, поскольку Term имеет атрибут Map Я думаю, что это не круговая ссылка, которая вызывает переполнение стека.

Выполняя некоторую отладку, я увидел, что переполнение стека происходит, потому что в конце spring-data продолжает создавать только этот термин (не другие, поэтому я не вижу круговой ссылки):

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(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 - нет.

1 Ответ

0 голосов
/ 10 февраля 2020

У меня действительно была круговая ссылка (точнее, собственная ссылка).

Я нашел обходной путь, заключающийся в создании @DBRef атрибутов lazy=true и реализации Пользовательский сериализатор класса Term, который имеет собственную ссылку (или круговую ссылку). Причиной реализации пользовательского сериализатора является то, что я могу сохранить набор объектов, которые уже были сериализованы, и если мне придется снова разделить объект, я просто не буду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...