Error Building Json of an Object retrieved by Hibernate

2

Error constructing Json from an object retrieved by Hibernate.

session.getTransaction().begin();        
ArrayList<Cliente> lista = new ArrayList<>(session.createCriteria(Cliente.class).list());
String json = new Gson().toJson(lista); // o erro acontece aqui
session.close();

return json;

Error Log

java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
    com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:67)
    com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    com.google.gson.internal.bind.ArrayTypeAdapter.write(ArrayTypeAdapter.java:93)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
    com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
    com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
    com.google.gson.Gson.toJson(Gson.java:593)
    com.google.gson.Gson.toJson(Gson.java:572)
    com.google.gson.Gson.toJson(Gson.java:527)
    com.google.gson.Gson.toJson(Gson.java:507)
    com.embrapa.pragasdocampo.resource.PragaResource.getLista(PragaResource.java:32)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:483)
    com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
    com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185)
    com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1465)
    com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1396)
    com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1345)
    com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1335)
    com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
    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)
    
asked by anonymous 13.11.2014 / 15:08

1 answer

3

I came to the conclusion after several searches and the problem is that the Client object has another Category object as its attribute. The data of the client object is in memory, since the data of the Category have not been taken from the database yet, Category is referenced with a proxy, that is, hibernate only takes that object from the database when you give a get in it to not occur outdated data problem. And it is no use creating a new Object that receives another, because it is only receiving the reference, the solution that worked was to make a clone of the object. creating an @Override clone method of the Client object. example

public Cliente clone(){
        Cliente cliente = new Cliente();
        cliente.setNome(nome);
        cliente.setSobreNome(sobreNome);
        //...
        cliente.setCategoria(categoria.clone()); // dentro de categoria vc cria o mesmo método clone da mesma forma que foi feito aqui.
        return cliente;
}

Be careful not to call the super method because if there is a N to N relationship, it will have to be handled, or it will give you a problem.

Do not forget to create the clone method in the Category class, this is critical.

public Categoria clone(){
    Categoria categoria = new Categoria();
    categoria.setId(id)
    categoria.setNome(nome);
    return categoria;
}

In my case, Hibernate is returning a list of Clients, so just implement it the best way to find a method that clones all clients into a new ArrayList.

Regarding the cost of processing, I'm not the best to answer, but so far it's the only solution I've found better.

  

Update 29 Nov 2014

     

I've been studying a bit more about JPA and I've decided to add one more   little bit of information in this post.

     

By default JPA:

     

• Every time a relationship ends in One (OneToOne,   ManyToOne) it will be by default EAGER.

     

• Every time a relationship ends in Many (OneToMany,   ManyToMany) it will default to LAZY.

     

EAGER means that when you search for a Client object that has Category attribute (Other object), in the act of Select Client in the database   data, the category object will be loaded into memory.

     

LAZY means that when you search for a Client object that has a Category attribute (Other object), in the act of the Select Client in the database   data, the category object will not be loaded into memory only in the   when the client.getCategory () method is invoked.

     

This is a JPA pattern, but can be changed, and possibly the   Hibernate is doing this.

     

It may not relate to my problem, but I found it interesting   share this concept.

    
14.11.2014 / 03:27