在MySQL/Java/Hibernate中保存大字符串

在MySQL/Java/Hibernate中保存大字符串,java,mysql,hibernate,jpa,Java,Mysql,Hibernate,Jpa,我正在尝试将json文档保存到mysql 8数据库中。此json文档超过1GB,因此列类型为longtext以处理额外的大小 然而,每当我试图在java大小上保存json blob时,它就会抛出一个关于字符串太长的错误。我的代码: package com.cpa.ipf.bo.forecast; import com.cpa.ipf.bo.CostCentre; import com.vladmihalcea.hibernate.type.json.JsonStringType; import

我正在尝试将json文档保存到mysql 8数据库中。此json文档超过1GB,因此列类型为longtext以处理额外的大小

然而,每当我试图在java大小上保存json blob时,它就会抛出一个关于字符串太长的错误。我的代码:

package com.cpa.ipf.bo.forecast;

import com.cpa.ipf.bo.CostCentre;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;

import javax.persistence.*;
import java.sql.Clob;
import java.time.LocalDateTime;
import java.util.Objects;

@Entity
public class ForecastMetadata {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Long userId;

    @ManyToOne
    private CostCentre costCentre;



    private String name;

    private Boolean viewableByAll;

    @Enumerated(EnumType.STRING)
    private ForecastStatus status;

    private LocalDateTime tsCreated;

    private LocalDateTime tsFinished;

    @Lob
    private Clob forecastBody;

    public ForecastMetadata(Long id, Long userId, CostCentre costCentre, String name, Boolean viewableByAll, ForecastStatus status, LocalDateTime tsCreated, LocalDateTime tsFinished, Clob forecastBody) {
        this.id = id;
        this.userId = userId;
        this.costCentre = costCentre;
        this.name = name;
        this.viewableByAll = viewableByAll;
        this.status = status;
        this.tsCreated = tsCreated;
        this.tsFinished = tsFinished;
        this.forecastBody = forecastBody;
    }

    public ForecastMetadata() {}

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public CostCentre getCostCentre() {
        return costCentre;
    }

    public void setCostCentre(CostCentre costCentre) {
        this.costCentre = costCentre;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean getViewableByAll() {
        return viewableByAll;
    }

    public void setViewableByAll(Boolean viewableByAll) {
        this.viewableByAll = viewableByAll;
    }

    public ForecastStatus getStatus() {
        return status;
    }

    public void setStatus(ForecastStatus status) {
        this.status = status;
    }

    public LocalDateTime getTsCreated() {
        return tsCreated;
    }

    public void setTsCreated(LocalDateTime tsCreated) {
        this.tsCreated = tsCreated;
    }

    public LocalDateTime getTsFinished() {
        return tsFinished;
    }

    public void setTsFinished(LocalDateTime tsFinished) {
        this.tsFinished = tsFinished;
    }

    public Clob getForecastBody() {
        return forecastBody;
    }

    public void setForecastBody(Clob forecastBody) {
        this.forecastBody = forecastBody;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ForecastMetadata that = (ForecastMetadata) o;
        return Objects.equals(id, that.id) &&
                Objects.equals(userId, that.userId) &&
                Objects.equals(costCentre, that.costCentre) &&
                Objects.equals(name, that.name) &&
                Objects.equals(viewableByAll, that.viewableByAll) &&
                status == that.status &&
                Objects.equals(tsCreated, that.tsCreated) &&
                Objects.equals(tsFinished, that.tsFinished) &&
                Objects.equals(forecastBody, that.forecastBody);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, userId, costCentre, name, viewableByAll, status, tsCreated, tsFinished, forecastBody);
    }

    @Override
    public String toString() {
        return "ForecastMetadata{" +
                "id=" + id +
                ", userId=" + userId +
                ", costCentre=" + costCentre +
                ", name='" + name + '\'' +
                ", viewableByAll=" + viewableByAll +
                ", status=" + status +
                ", tsCreated=" + tsCreated +
                ", tsFinished=" + tsFinished +
                ", forecastBody='" + forecastBody + '\'' +
                '}';
    }
}
错误:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
        at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:68) ~[na:1.8.0_252]
        at java.lang.StringBuilder.<init>(StringBuilder.java:101) ~[na:1.8.0_252]
        at com.mysql.cj.ClientPreparedQueryBindings.setString(ClientPreparedQueryBindings.java:628) ~[mysql-connector-java-8.0.20.jar!/:8.0.20]
        at com.mysql.cj.ClientPreparedQueryBindings.setCharacterStream(ClientPreparedQueryBindings.java:335) ~[mysql-connector-java-8.0.20.jar!/:8.0.20]
        at com.mysql.cj.ClientPreparedQueryBindings.setCharacterStream(ClientPreparedQueryBindings.java:366) ~[mysql-connector-java-8.0.20.jar!/:8.0.20]
        at com.mysql.cj.jdbc.ClientPreparedStatement.setCharacterStream(ClientPreparedStatement.java:1519) ~[mysql-connector-java-8.0.20.jar!/:8.0.20]
        at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4$1.doBind(ClobTypeDescriptor.java:124) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:90) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:286) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:281) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:56) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2818) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister$4.bindValues(AbstractEntityPersister.java:3025) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3032) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3558) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:98) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:492) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:197) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:181) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:216) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:334) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:289) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:195) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84) ~[hibernate-entitymanager-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
        at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
java.lang.OutOfMemoryError:请求的数组大小超过VM限制
在java.lang.AbstractStringBuilder.(AbstractStringBuilder.java:68)~[na:1.8.0_252]
在java.lang.StringBuilder.(StringBuilder.java:101)~[na:1.8.0_252]
在com.mysql.cj.ClientPreparedQueryBindings.setString(ClientPreparedQueryBindings.java:628)~[mysql-connector-java-8.0.20.jar!/:8.0.20]
在com.mysql.cj.ClientPreparedQueryBindings.setCharacterStream(ClientPreparedQueryBindings.java:335)~[mysql-connector-java-8.0.20.jar!/:8.0.20]
在com.mysql.cj.ClientPreparedQueryBindings.setCharacterStream(ClientPreparedQueryBindings.java:366)~[mysql-connector-java-8.0.20.jar!/:8.0.20]
在com.mysql.cj.jdbc.ClientPreparedStatement.setCharacterStream(ClientPreparedStatement.java:1519)~[mysql-connector-java-8.0.20.jar!/:8.0.20]
在org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4$1.doBind(ClobTypeDescriptor.java:124)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:90)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:286)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:281)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:56)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.persister.entity.AbstractEntityPersister.deterhymate(AbstractEntityPersister.java:2843)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.persister.entity.AbstractEntityPersister.deterhymate(AbstractEntityPersister.java:2818)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.persister.entity.AbstractEntityPersister$4.bindValues(AbstractEntityPersister.java:3025)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3032)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3558)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:98)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:492)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:197)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:181)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:216)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:334)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:289)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:195)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.AbstractSaveEventListener.SaveWithGenerateId(AbstractSaveEventListener.java:126)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)~[hibernate-entitymanager-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
在org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]

有没有办法解决这个问题?

我看到很多评论说应该增加堆大小,但是错误消息

请求的数组大小超过VM限制

实际上意味着试图创建一个数组,其长度将超过平台特定的最大可能数组长度(通常约为
整数.MAX_值
)。增加堆大小不会有帮助。这不是对内存中数组大小的限制,而是对数组可以拥有的最大有效索引的限制

现在,让我们看看导致问题的代码:

StringBuilder buf = new StringBuilder((int) (x.length() * 1.1));
在上面的代码中,
x
表示您的
Clob的内容
AbstractStringBuilder(int capacity) {
        if (COMPACT_STRINGS) {
            value = new byte[capacity];
            coder = LATIN1;
        } else {
            value = StringUTF16.newBytesFor(capacity);
            coder = UTF16;
        }
    }
boolean useLength = this.useStreamLengthsInPrepStmts.getValue();
String forcedEncoding = this.session.getPropertySet().getStringProperty(PropertyKey.clobCharacterEncoding).getStringValue();
if (useLength && (length != -1)) {
    c = new char[length];
    int numCharsRead = Util.readFully(reader, c, length); // blocks until all read
    if (forcedEncoding == null) {
        setString(parameterIndex, new String(c, 0, numCharsRead));
    } else {
        setBytes(parameterIndex, StringUtils.getBytes(new String(c, 0, numCharsRead), forcedEncoding));
    }
} else {
    c = new char[4096];
    StringBuilder buf = new StringBuilder();
    while ((len = reader.read(c)) != -1) {
        buf.append(c, 0, len);
    }
    if (forcedEncoding == null) {
        setString(parameterIndex, buf.toString());
    } else {
        setBytes(parameterIndex, StringUtils.getBytes(buf.toString(), forcedEncoding));
    }
}
public void setBinaryStream(int parameterIndex, InputStream x, int length) {
        if (x == null) {
            setNull(parameterIndex);
        } else {
            this.bindValues[parameterIndex].setNull(false);
            this.bindValues[parameterIndex].setIsStream(true);
            this.bindValues[parameterIndex].setMysqlType(MysqlType.BLOB); // TODO use length to find the right BLOB type
            this.bindValues[parameterIndex].setStreamValue(x, length);
        }
    }