Что вызывает безопасную очистку (коллекции) Spring Boot Fail-safe

У меня есть приложение Java Spring Boot со следующими объектами, связанными с приведенным ниже исключением.

Sпродукт

@Entity
@Table(
        name = "product",
        indexes = @Index(
                name = "idx_asin",
                columnList = "asin",
                unique = true
        )
)
public class SProduct implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @Column(name = "asin", unique = false, nullable = false, length = 10)
    private String asin;
    @Column(name = "rootcategory")
    private Long rootcategory;
    @Column(name = "imageCSV", unique = false, nullable = true, length = 350)
    private String imagesCSV;
    @Column(name = "title", unique = false, nullable = true, length = 350)
    private String title;
    private Date created;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "mainProduct", cascade = CascadeType.ALL)
    private Set<FBT> fbts;
    @OneToOne(fetch = FetchType.EAGER, mappedBy = "downloadProductId", cascade = CascadeType.ALL)
    private Download download;

FBT

@Entity
@Table(
    name = "fbt",
    uniqueConstraints = {@UniqueConstraint(columnNames = {"main_product_id" , "collection"})},
    indexes = {@Index(
        name = "idx_main_product_id",
        columnList = "main_product_id",
        unique = false),
        @Index(
        name = "idx_product_fbt1id",
        columnList = "product_fbt1_id",
        unique = false),
        @Index(
        name = "idx_product_fbt2id",
        columnList = "product_fbt2_id",
        unique = false)
        }
)
public class FBT implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    @ManyToOne
    @JoinColumn(name = "main_product_id")
    private SProduct mainProduct;
    @ManyToOne
    @JoinColumn(name = "product_fbt1_id")
    private SProduct sproductFbt1;
    @ManyToOne
   
    @JoinColumn(name = "product_fbt2_id")
    private SProduct sproductFbt2;
    @Column(name = "bsr", nullable = false)
    private int bsr;
    private Date collection;

У меня был следующий запрос в моем репозитории fbt

  FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);

что вызвало исключение вывода следующих сообщений, когда данные существуют в базе данных для mainProduct и collection, но в противном случае возвращает null.

  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@69b7fcfc&lt;rs=HikariProxyResultSet@325408381 wrapping com.mysql.jdbc.JDBC42ResultSet@108693fa&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@47c40535&lt;rs=HikariProxyResultSet@2005129089 wrapping com.mysql.jdbc.JDBC42ResultSet@9894f70&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5b0cd175&lt;rs=HikariProxyResultSet@1598144514 wrapping com.mysql.jdbc.JDBC42ResultSet@6a7ff475&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@f67e2cc&lt;rs=HikariProxyResultSet@319200129 wrapping com.mysql.jdbc.JDBC42ResultSet@215b8a6&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5961afc0&lt;rs=HikariProxyResultSet@1772496904 wrapping com.mysql.jdbc.JDBC42ResultSet@5956a59b&gt;</message>
  <message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
  <message>HHH000100: Fail-safe cleanup (collections) : 

Я решил отказаться от вышеизложенного и написать @query для подсчета, поскольку мне нужно только определить, существуют ли данные или нет, и это предотвратило проблему, которая заставляет меня думать, что я должен изменить весь свой код для использования @query.

 @Query("select count(*) as count from FBT where main_product_id = :id and collection= :collection")
    int countByMainProductIdAndCollection(@Param("id") long id, @Param("collection") Date collection);

Хотя это также происходит, по-видимому, случайным образом при обновлениях в базе данных одного SProduct, когда продукт уже существует в базе данных.

SProductRepo.saveAndFlush(s);

Я говорю «случайным образом», поскольку 11 приложений, выполняющих один и тот же код, выходят через случайные промежутки времени с указанными выше сообщениями. Код не создает исключений, и 10000 успешных обновлений базы данных происходят с тем же кодом, который приводит к сбою. Код останавливается при попытке обновить базу данных, в которой он работал ранее.

""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@5c414639<rs=HikariProxyResultSet@1241510017 wrapping Result set representing update count of 13>
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.CollectionLoadContext - HHH000160: On CollectionLoadContext#cleanup, localLoa
dingCollectionKeys contained [1] entries
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@5595c065<rs=HikariProxyResultSet@2140082434 wrapping Result set representing update count of 14>
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.CollectionLoadContext - HHH000160: On CollectionLoadContext#cleanup, localLoa
dingCollectionKeys contained [1] entries
""2018-12-28 00:56:06 [KeepaAPI-RetryScheduler] WARN  org.hibernate.engine.loading.internal.LoadContexts - HHH000100: Fail-safe cleanup (collections) : org.hibernate.eng
ine.loading.internal.CollectionLoadContext@2956fe24<rs=HikariProxyResultSe

Кроме того, запрос SProduct findByAsin (String asin) вызывает ту же проблему, однако запрос в базе данных работает отлично, и это работало при весенней загрузке.

mysql> select * from product where asin = "B004FXJOQO";
| id | asin       | created    | imagecsv                                                                        | rootcategory | title                                                                                                        |  9 | B004FXJOQO | 2018-08-04 | 41T0ZwTvSSL.jpg,61V90AZKbGL.jpg,51AdEGCTZqL.jpg,51LDnCYfR0L.jpg,71bbIw43PjL.jpg |       228013 | Dual Voltage Tester, Non Contact Tester for High and Low Voltage with 3-m Drop Protection Klein Tools NCVT-2 |
1 row in set (0.00 sec)

Я хотел бы знать, каковы общие причины создания такого рода сообщений?

Почему они останавливают мое приложение, несмотря на операторы try catch вокруг операторов вставки, которые являются последними выполненными операторами в моем коде?

Есть ли полезные настройки отладки журнала для определения точной причины создания сообщений?

Есть ли способ отключить или контролировать эту функцию?

Пом

  <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
        <maven.test.skip>true</maven.test.skip>
    </properties>
    <repositories>
        <repository>
            <id>Keepa</id>
            <name>Keepa Repository</name>
            <url>https://keepa.com/maven/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.18</version>
        </dependency>
        <dependency>
            <groupId>com.google.api-client</groupId>
            <artifactId>google-api-client</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client-jetty</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-oauth2</artifactId>
            <version>v1-rev120-1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client-java6</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client</artifactId>
            <version>1.22.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-gmail</artifactId>
            <version>v1-rev48-1.22.0</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.5.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-nop</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>
        <dependency>
            <groupId>com.myjeeva.digitalocean</groupId>
            <artifactId>digitalocean-api-client</artifactId>
            <version>2.16</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.keepa.api</groupId>
            <artifactId>backend</artifactId>
            <version>LATEST</version>
        </dependency>
        <dependency>
            <groupId>org.jdeferred</groupId>
            <artifactId>jdeferred-core</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build

Я увеличил объем памяти с 1 ГБ до 2 ГБ, однако объем памяти составляет только 30% от того, что доступно.

Есть мысли относительно того, в чем проблема?

Попробуйте existsByMainProductAndCollection(), если вам не нужны данные

Maruthi Adithya 28.12.2018 11:12

Сталкивались ли вы с этой проблемой вместе с упомянутой? "java.lang.OutOfMemoryError: превышен предел накладных расходов сборщика мусора"

Md. 05.02.2020 22:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
15
2
22 286
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Похоже, вы загружаете в свое приложение огромное количество данных.

Метод

FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);

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

Один из способов сделать это - использовать упомянутый вами запрос, а другой -

Long countByMainProductAndCollection(SProduct mainProduct, Date collection);

Или

Boolean existsByMainProductAndCollection(SProduct mainProduct, Date collection)

Да, для SProductRepo.saveAndFlush (s) я сохраняю только один SProduct. Хотел бы разобраться в проблеме и получить ответы на эти вопросы за вознаграждение.

conteh 28.12.2018 12:03

странно то, что эти методы findby должны возвращать только несколько записей. У меня такая же проблема при выполнении SProductRepo.findByAsin (asin); однако в базе данных есть только одна запись с этим asin, и я могу запросить ее. Это тайм-ауты, учитывая 1,5 миллиона заданий?

conteh 29.12.2018 19:06

Во-первых, это ошибка гибернации, обрабатываемая org.hibernate.engine и не имеющая ничего общего с Spring Boot.

Это может произойти, если вы извлекаете большие объемы данных, например десятки тысяч сущностей, с помощью ваших запросов HQL.

Это также может иметь место, если вы сопоставили ассоциацию «один ко многим», которая имеет множество дочерних сущностей, и из-за двунаправленного сопоставления набор результатов реплицируется бесконечно.

См. Ссылку ниже для получения советов по высокопроизводительному JPA.

https://vladmihalcea.com/14-high-performance-java-persistence-tips/

Ответ принят как подходящий

Можно с @Fetch(value = SELECT) попробовать?

@OneToMany(fetch = FetchType.EAGER, mappedBy = "mainProduct", cascade = CascadeType.ALL)
@Fetch(value=FetchMode.SELECT)
private Set<FBT> fbts;

В моем случае это было из-за того, что сущности рекурсивно вызывали хэш-код друг друга, если вы используете lombock, удалите его и сделайте самостоятельно. Поместите точку останова отладчика на методы двух хэш-кодов. Вы поймете, что они зовут друг друга. Удалите, например, из метода хэш-кода первой сущности ссылку второй сущности.

Если вы используете @Data, удалите его и повторите попытку. Данные эквивалентны Getter Setter RequiredArgsConstructor ToString EqualsAndHashCode.

Harinath 08.08.2019 01:14

с lombok вы можете использовать атрибут exclude с анотацией EqualsAndHashCode, чтобы исключить поля, которые вызывают переполнение

Y.LAGHOUAZI 06.10.2020 11:00

Спасибо! Это было единственное решение, которое сработало для меня! Я реализовал equals и hashCode для своих POJO, и он начал работать для меня !!!

Zaki Petrov 30.10.2020 21:42

У меня была эта проблема при использовании Set, но когда я все-таки перехожу в список, она решается Вы должны использовать

  private List<FBT> fbts;

В моем случае я использовал автоматически сгенерированный метод Repository, который вернул List<MyData>. Оказывается, 2000 сущностей - это слишком много для Hibernate. Я исправил проблему, заменив его методом, возвращающим Stream<MyData>, а затем сопоставив объекты с созданной вручную структурой MyDataDetached.

В моем случае я получал "java.lang.StackOverflowError: null" (ранее также несколько сообщений журнала «Безотказная очистка (сборники)») при запуске метода JPA спасти для определенного объекта с двунаправленными отношениями @ManyToOne и @Один ко многим. Любопытно, что он не работал только с Oracle и PostgreSQL, но работал нормально в MySQL, MariaDB и SQLServer.

Итак, проблема заключалась в том, что ломбок с Хэш-код в объектах @Один ко многим.

Я решил установить эту аннотацию в этих объектах на уровне класса:

@EqualsAndHashCode (exclude = "nameAttributeInThisClassWithOneToMany")

Спас мой день, чувак, это потрясающе!

DevGuyAhnaf 23.10.2021 09:15

Другие вопросы по теме