[英]What causes Spring Boot Fail-safe cleanup (collections) to occur
我有一個 Java Spring Boot 應用程序,其中包含與以下異常相關的以下實體
產品
@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 和集合的數據庫中存在數據時,導致以下消息輸出異常,否則返回 null。
<message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@69b7fcfc<rs=HikariProxyResultSet@325408381 wrapping com.mysql.jdbc.JDBC42ResultSet@108693fa></message>
<message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
<message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@47c40535<rs=HikariProxyResultSet@2005129089 wrapping com.mysql.jdbc.JDBC42ResultSet@9894f70></message>
<message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
<message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5b0cd175<rs=HikariProxyResultSet@1598144514 wrapping com.mysql.jdbc.JDBC42ResultSet@6a7ff475></message>
<message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
<message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@f67e2cc<rs=HikariProxyResultSet@319200129 wrapping com.mysql.jdbc.JDBC42ResultSet@215b8a6></message>
<message>HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [1] entries</message>
<message>HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@5961afc0<rs=HikariProxyResultSet@1772496904 wrapping com.mysql.jdbc.JDBC42ResultSet@5956a59b></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) 查詢會導致同樣的問題,但是數據庫中的查詢運行良好,這曾經在 Spring Boot 中運行。
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
我將內存從 1gb 增加到 2gb,但是內存只有可用內存的 30%。
關於問題是什么的任何想法?
就我而言,這是因為實體遞歸地調用彼此的哈希碼,如果您使用 lombok 將其刪除並自行制作。將調試器的斷點放在兩個哈希碼的方法上。 你會知道他們在互相打電話。 例如從第一個實體的哈希碼方法中刪除第二個實體的鏈接。
首先是org.hibernate.engine
處理的Hibernate Error,與Spring Boot無關。
如果您正在獲取大量數據,例如使用 HQL 查詢獲取數萬個實體,則可能會發生這種情況。
如果您映射了具有許多子實體的一對多關聯,並且由於雙向映射結果集無限復制,情況也可能如此。
有關高性能 JPA 提示,請參閱下面的鏈接。
https://vladmihalcea.com/14-high-performance-java-persistence-tips/
我在使用 Set 時遇到了這個問題,但是當我更改為 List 時它已經解決了你應該使用
private List<FBT> fbts;
你可以試試@Fetch(value = SELECT)
嗎?
@OneToMany(fetch = FetchType.EAGER, mappedBy = "mainProduct", cascade = CascadeType.ALL)
@Fetch(value=FetchMode.SELECT)
private Set<FBT> fbts;
看起來您在應用程序中加載了大量數據。
方法
FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);
將加載所有匹配的數據。 但是您只需要 count 嘗試准確返回數據計數而不是所有數據的查詢。
一種方法是使用您提到的查詢,另一種方法是
Long countByMainProductAndCollection(SProduct mainProduct, Date collection);
或者
Boolean existsByMainProductAndCollection(SProduct mainProduct, Date collection)
就我而言,我使用了一個自動生成的Repository
方法,該方法返回List<MyData>
。 事實證明,2000 個實體對於 Hibernate 來說太多了。 我通過用返回Stream<MyData>
的方法替換它來解決這個問題,然后將實體映射到手工制作的 struct MyDataDetached
。
在我的情況下,在具有雙向關系@ManyToOne和@OneToMany的特定實體上運行 JPA保存方法時,我收到“java.lang.StackOverflowError:null” (以前還有多個“故障安全清理(集合)”日志消息)。 奇怪的是,它只在 Oracle 和 PostgreSQL 上失敗,但在 MySQL、MariaDB 和 SQLServer 上運行良好。
所以,問題是用在@OneToMany實體的哈希碼龍目島。
我解決了它在級別類的實體中設置此注釋的問題:
@EqualsAndHashCode(exclude = "nameAttributeInThisClassWithOneToMany")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.