在MySQL/Java/Hibernate中保存大字符串
我正在尝试将json文档保存到mysql 8数据库中。此json文档超过1GB,因此列类型为longtext以处理额外的大小 然而,每当我试图在java大小上保存json blob时,它就会抛出一个关于字符串太长的错误。我的代码:在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
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);
}
}