hibernate 什么导致Sping Boot 故障安全清理(收集)发生

e3bfsja2  于 2023-10-23  发布在  其他
关注(0)|答案(8)|浏览(123)

我有一个Java Sping 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和集合的数据时输出异常,否则返回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);

尽管这类似地也在一个S产品的数据库更新时随机发生,而该产品已经存在于数据库中。

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

此外,SProductfindByAsin(Stringasin)查询也会导致同样的问题,但是数据库中的查询工作得很好,这在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语句是我代码中最后执行的语句?
是否有日志调试设置可用于确定生成消息的确切原因?
是否有方法关闭或控制此功能?

Pom

<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%。
有什么想法吗?

9udxz4iz

9udxz4iz1#

在我的例子中,这是因为实体递归地调用对方的散列代码,如果你使用lombock,请删除它并自己创建它。你会发现他们在互相打电话。例如,从第一个实体的hashcode方法中删除第二个实体的链接。

rfbsl7qr

rfbsl7qr2#

我在使用Set时遇到了这个问题,但当我更改为List时,它已解决,您应该使用

private List<FBT> fbts;
yshpjwxd

yshpjwxd3#

首先,这是一个由org.hibernate.engine处理的Hibernate错误,与Sping Boot 无关。
如果您正在获取大量数据,例如使用HQL查询获取数万个实体,则可能会发生这种情况。
如果你Map了一个一对多的关联,它有许多子实体,并且由于双向Map,结果集无限复制,也可能是这种情况。
请参阅下面的链接以获取高性能JPA提示。
https://vladmihalcea.com/14-high-performance-java-persistence-tips/

f87krz0w

f87krz0w4#

在我的例子中,我得到**“java.lang.StackOverflowError:在具有双向关系 @ManyToOne@OneToMany 的特定实体上运行JPA * 保存 * 方法时,奇怪的是,它只在Oracle和PostgreSQL上失败,但在MySQL,MariaDB和SQLServer上工作正常。
所以问题是 lombokHashCode@OneToMany 实体中。
我解决了它设置这个注解中的实体在级别类:

  • @ browsAndHashCode(exclude =“nameAttributeInThisClassWithOneToMany”)*
xqk2d5yq

xqk2d5yq5#

你可以试试@Fetch(value = SELECT)吗?

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

fnvucqvd6#

看起来你在应用程序中加载了大量的数据。
述的方法

FBT findByMainProductAndCollection(SProduct mainProduct,Date collection);

将加载所有匹配的数据。但你只需要count尝试查询,确切地返回count数据而不是所有数据。
一种方法是使用你提到的查询,另一种方法是

Long countByMainProductAndCollection(SProduct mainProduct, Date collection);

Boolean existsByMainProductAndCollection(SProduct mainProduct, Date collection)
mwkjh3gx

mwkjh3gx7#

在我的例子中,我使用了一个自动生成的Repository方法,它返回List<MyData>。事实证明,2000个实体对Hibernate来说太多了。我修复了这个问题,将其替换为一个返回Stream<MyData>的方法,然后将实体Map到手工构建的结构MyDataDetached

w8f9ii69

w8f9ii698#

我也遇到了同样的问题,我通过在上面添加OneToMany和ManyToOne来解决它。
如果你想用父对象而不是子对象来生成JSON,你可以用@JsonBackReference来注解product,用@JsonManagedReference来注解ftb,或者将@JsonIgnore添加到这两个实体中。

相关问题