首页 > 解决方案 > 使用 JPA 将 JSON 存储到 postgres 中?

问题描述

我正在尝试使用 EclipseLink JPA 实现将 JSON 字符串从我的 AS 持久化到 postgresql 中。

为此,我JsonObject在 JPA 中使用了 javax 并编写了一个转换器来转换为PGObject

JPA:

import javax.json.JsonObject;

@Entity
@Table(name="\"CONTAINER\"")
@NamedQuery(name="Container.findAll", query="SELECT r FROM Container r")
public class Container implements ResourceJPA, Serializable {

    @Column(name="\"creationTime\"")
    private Timestamp creationTime;

    @Column(name="\"creator\"")
    private String creator;

    @Convert(converter=JsonConverter.class) 
    @Column(name="\"customAttribute\"", columnDefinition = "jsonb")
    private  JsonObject customAttribute;

...

}

json转换器:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import javax.json.Json;
import javax.json.JsonObject;
import javax.persistence.Converter;
import org.postgresql.util.PGobject;

@Converter(autoApply = true)
public class JsonConverter implements javax.persistence.AttributeConverter<JsonObject, Object> {

  private static final long serialVersionUID = 1L;
  private static ObjectMapper mapper = new ObjectMapper();

  @Override
  public Object convertToDatabaseColumn(JsonObject objectValue) {
    try {
      PGobject out = new PGobject();
      out.setType("json");
      out.setValue(objectValue.toString());
      return out;
    } catch (Exception e) {
      throw new IllegalArgumentException("Unable to serialize to json field ", e);
    }
  }

  @Override
  public JsonObject convertToEntityAttribute(Object dataValue) {
    try {
      if (dataValue instanceof PGobject && ((PGobject) dataValue).getType().equals("json")) {
        return mapper.reader(new TypeReference<JsonObject>() {
        }).readValue(((PGobject) dataValue).getValue());
      }
      return Json.createObjectBuilder().build();
    } catch (IOException e) {
      throw new IllegalArgumentException("Unable to deserialize to json field ", e);
    }
  }
}

我收到以下错误java.io.NotSerializableException

Caused by: Exception [EclipseLink-67] (Eclipse Persistence Services - 2.4.2.v20130514-5956486): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Could not serialize object into byte array.
Internal Exception: java.io.NotSerializableException: org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl
Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[customAttribute-->CONTAINER.customAttribute]
Descriptor: RelationalDescriptor(...jpa.Container --> [DatabaseTable(CONTAINER)])
        at org.eclipse.persistence.exceptions.DescriptorException.notSerializable(DescriptorException.java:1228)
        at org.eclipse.persistence.mappings.converters.SerializedObjectConverter.convertObjectValueToDataValue(SerializedObjectConverter.java:89)
        at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.getFieldValue(AbstractDirectMapping.java:746)
        at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.writeFromObjectIntoRow(AbstractDirectMapping.java:1241)
        at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRow(ObjectBuilder.java:1201)
        at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildRow(ObjectBuilder.java:1189)
        at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:436)
        at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
        at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
        at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:286)
        at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
        at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
        at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:751)
        at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
        at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2879)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1607)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1589)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1540)
        at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
        at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:125)
        at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3945)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1423)
        at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:638)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithPreBuiltChangeSet(UnitOfWorkImpl.java:1569)
        at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.writeChanges(RepeatableWriteUnitOfWork.java:445)
        at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:798)
        ... 255 more
Caused by: java.io.NotSerializableException: org.glassfish.json.JsonObjectBuilderImpl$JsonObjectImpl
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
        at org.eclipse.persistence.mappings.converters.SerializedObjectConverter.convertObjectValueToDataValue(SerializedObjectConverter.java:86)
        ... 280 more


jsonb将 JSON 存储到 postgres字段中是否有更好的选择?

标签: javapostgresqljpaeclipselinkconverters

解决方案


推荐阅读