java - Spring Boot JPA ManyToMany 导致 OutOfMemoryError

标签 java spring-boot jpa out-of-memory

我有一个 Spring boot 应用程序,我试图插入一部与国家/地区相关的电影,但几分钟后抛出异常。简化实体:

电影:

public class Movie implements Serializable {

    ...

    @ManyToMany(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE
    })
    @JoinTable(name = "movies_countries",
        joinColumns = @JoinColumn(name = "id_movie"),
        inverseJoinColumns = @JoinColumn(name = "id_country")
    )
    private Set<Country> countries = new HashSet<>();

    public Set<Country> getCountries() {
        return this.countries;
    }

    public void setCountries(Set<Country> countries) {
        this.countries = countries;
    }

    public void addCountry(Country country) {
        getCountries().add(country);
        country.getMovies().add(this); // Point where it gets blocked
    }
    ...
}

国家/地区:

public class Country implements Serializable {

    ...

    @ManyToMany(mappedBy = "countries")
    private Set<Movie> movies = new HashSet<>();

    public Set<Movie> getMovies() {
            return movies;
    }

    public void setMovies(Set<Movie> movies) {
        this.movies = movies;
    }

    ...

}

以及将电影与国家联系起来的方法:

private void insertCountries(final List<String> countries, final EntityManager entityManager, final Movie movie) {
    for (String strCountry: countries) {
        Country country = this.getCountry(entityManager, strCountry);
        movie.addCountry(country);
    }
}

异常(exception):

Exception in thread "Thread-6" java.lang.OutOfMemoryError: Java heap space
    at io.netty.buffer.PooledDirectByteBuf$1.newObject(PooledDirectByteBuf.java:35)
    at io.netty.buffer.PooledDirectByteBuf$1.newObject(PooledDirectByteBuf.java:32)
    at io.netty.util.Recycler.get(Recycler.java:158)
    at io.netty.buffer.PooledDirectByteBuf.newInstance(PooledDirectByteBuf.java:40)
    at io.netty.buffer.PoolArena$DirectArena.newByteBuf(PoolArena.java:786)
    at io.netty.buffer.PoolArena.allocate(PoolArena.java:145)
    at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:332)
    at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:185)
    at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:176)
    at io.netty.channel.nio.AbstractNioChannel.newDirectBuffer(AbstractNioChannel.java:448)
    at io.netty.channel.nio.AbstractNioByteChannel.filterOutboundMessage(AbstractNioByteChannel.java:275)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:881)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1365)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:816)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:723)
    at io.netty.handler.logging.LoggingHandler.write(LoggingHandler.java:249)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:816)
    at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:723)
    at io.netty.channel.ChannelDuplexHandler.write(ChannelDuplexHandler.java:106)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
    at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730)
    at io.netty.channel.AbstractChannelHandlerContext.access$1700(AbstractChannelHandlerContext.java:38)
    at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1127)
    at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1174)
    at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1098)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:495)
2020-03-02 12:41:54,741 WARN  [http-nio-8090-exec-2] com.zaxxer.hikari.pool.PoolBase: HikariPool-1 - Failed to validate connection com.mysql.jdbc.JDBC4Connection@35e38de8 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

为了尝试,我尝试将内存从 1 GB 增加到 2 GB,但它仍然出现。并非所有电影插页都会发生这种情况。

有什么建议吗?

最佳答案

多对多关系很棘手,不要使用级联配置,级联与保存实体有关,这里没有实体,只有关联,这个关联是由orm在幕后管理的监视底层集合中发生的情况,如果您看一下实现,则该集合实际上是某种用于检测其中变化的包。保存必须在所属端完成:没有mappedBy注释的端。

关于java - Spring Boot JPA ManyToMany 导致 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60489505/

相关文章:

java - Spring-Boot 无法添加 Google Guava 依赖

java - 如何在 SAST Checkmarx 之后解决 API Controller 中的 XSRF 跨站请求伪造 (CSRF)

java - 使用 Spring Web MVC 解耦后备存储

java - Spring JPA TransactionManager 未找到

java - 无法使用 Spring 配置 JPA

java - 阶乘程序没有给出正确的输出

java - Derby ,Java EE。对文件数据库运行集成测试,不会被丢弃

java - Spring security 5 迁移指南

java - 将流映射到原始索引列表

java - 如何在 API 调用中使用多个通配符