【问题标题】:java.lang.StackOverflowError for gson get methodsgson get 方法的 java.lang.StackOverflowError
【发布时间】:2019-07-23 15:38:11
【问题描述】:

我的宠物类看起来像这样(没有使用 getter 和 setter)。

@Entity
@Table(name = "pet")
@NamedQueries({
    @NamedQuery(name = "Pet.findAll", query = "SELECT p FROM Pet p")
    , @NamedQuery(name = "Pet.findById", query = "SELECT p FROM Pet p WHERE p.id = :id")
    , @NamedQuery(name = "Pet.findByName", query = "SELECT p FROM Pet p WHERE p.name = :name")
    , @NamedQuery(name = "Pet.findByBirth", query = "SELECT p FROM Pet p WHERE p.birth = :birth")
    , @NamedQuery(name = "Pet.findBySpecies", query = "SELECT p FROM Pet p WHERE p.species = :species")
    , @NamedQuery(name = "Pet.findByDeath", query = "SELECT p FROM Pet p WHERE p.death = :death")})
public class Pet implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false)
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "name", nullable = false, length = 45)
    private String name;
    @Basic(optional = false)
    @NotNull
    @Column(name = "birth", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date birth;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "species", nullable = false, length = 45)
    private String species;
    @Column(name = "death")
    @Temporal(TemporalType.DATE)
    private Date death;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pet")
    private Collection<Event> eventCollection;
    @JoinColumn(name = "owner_id", referencedColumnName = "id")
    @ManyToOne
    private Owner owner;

    public Pet() {
    }

    public Pet(Integer id) {
        this.id = id;
    }

    public Pet(Integer id, String name, Date birth, String species) {
        this.id = id;
        this.name = name;
        this.birth = birth;
        this.species = species;
    }

我有这个gson方法

@GET 
    @Path("/living")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getLivingPets(){
        return Response.ok().entity(gson.toJson(pf.getLivingPets())).build();
    }

和我的数据库外观方法

public List<Pet> getLivingPets() {

        EntityManager em = emf.createEntityManager();
        try {
            Query q = em.createQuery("select p from Pet p where p.death is null");

            return (List<Pet>) q.getResultList();
        } finally {
            em.close();
        }
    }

我收到了这个错误

输入异常报告

消息 java.lang.StackOverflowError

描述服务器遇到阻止它的内部错误 完成此请求。

异常

javax.servlet.ServletException: java.lang.StackOverflowError com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:420) com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558) com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733) javax.servlet.http.HttpServlet.service(HttpServlet.java:725) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)

根本原因

java.lang.StackOverflowError com.google.gson.stream.JsonWriter.beforeValue(JsonWriter.java:642) com.google.gson.stream.JsonWriter.open(JsonWriter.java:325) com.google.gson.stream.JsonWriter.beginObject(JsonWriter.java:308) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240) com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1018) com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)

【问题讨论】:

  • 可以发一下Pet类的结构吗?
  • 我现在添加了宠物类代码
  • 可能是类型问题(FutureTypeAdapter); json中的转换不知道怎么适配某种类型(但不知道是哪个)
  • 可能事件或所有者引用了一个或多个宠物,并且发生了循环解析...

标签: java gson jpql


【解决方案1】:

第一次更改如果您需要关闭流,那么最佳做法是使用 try-with-resources 语句 link

    try (EntityManager em = emf.createEntityManager()) {
        Query q = em.createQuery("select p from Pet p where p.death is null");

        return (List<Pet>) q.getResultList();
    }

版本 1 只发送 d 只发送你需要的字段

@GET 
@Path("/living")
@Produces(MediaType.APPLICATION_JSON)
public Response getLivingPets(){
    return Response.ok().entity(gson.toJson(pf.getLivingPets().stream().map(Dto::new).collect(Collectors.toList()))).build();
}

//adn 为你的 DTO 创建了类

public class Dto {
    private final Integer id;
    private final String name;

    public Dto(Pet pet) {
        this.id= pet.getId();
        this.name= pet.getName();
    }
}

第 2 版创建 TypeAdapter,其中是对 Pet 的反馈引用

@GET 
@Path("/living")
@Produces(MediaType.APPLICATION_JSON)
public Response getLivingPets(){
    Gson gson = new GsonBuilder().registerTypeAdapter(Owner.class, new PetAdapter()).create();
    return Response.ok().entity(gson.toJson(pf.getLivingPets())).build();
}

创建 PetAdapter

public class PetAdapter extends TypeAdapter<Owner> {

    @Override
    public void write(JsonWriter out, Owner value) throws IOException {

        out.beginObject();
        out.name("id");
        out.value(value.getId());
        out.endObject();

        //NOT USE PET
    }

    @Override
    public Owner read(JsonReader in) throws IOException {
        return null;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多