2017-07-14 4 views
0

Ich habe eine Java EE-Anwendung mit Hibernate und wild 10 erstellt. Ich habe keine Servlets, sondern eine REST API mit Java-API für RESTful WebService gebaut. Da meine Modelle immer größer geworden sind, habe ich meine Kollektionen von FetchType.EAGER bis FetchType.LAZY eingestellt. Jetzt bekomme ich eine LazyInitializationException mit der Nachricht could not initialize proxy - no Session. Ich denke, ich verstehe, warum das passiert, aber ich verstehe nicht, wenn Hibernate versucht, auf den Proxy zuzugreifen.Hibernate Lazy Laden in 3-Tier Java EE-Anwendung

Entity:

@Entity 
public class User implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Version 
    private Timestamp lastChanged; 

    @NotNull 
    private Date creationDate; 

    @ManyToMany 
    private Set<Entity> lazyEntity; 

    public User() { } 

    // getters and setters 
} 

DAO:

public interface UserDAO { 
    public List<User> getAll(); 
} 

Bean:

@Stateless 
@Remote(UserDAO.class) 
public class UserBean<User> implements UserDAO { 

    @PersistenceContext 
    protected EntityManager em; 

    @Override 
    public List<User> getAll() { 
     return this.em.createQuery("SELECT u FROM User u ORDER BY u.creationDate", User.class) 
         .getResultList(); 
    } 
} 

Endp unkt:

@Path("/users") 
@Stateless 
public class UsersEndpoint { 

    @EJB 
    private UserDAO userDAO; 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getAll() { 
     List<User> users = userDAO.getAll(); 
     if (users.size() == 0) 
      return Response.status(Response.Status.NOT_FOUND) 
          .build(); 
     return Response.ok(users).build(); 
    } 
} 

ist meine Frage, warum nicht die lazyEntity nur als null, aber ein Fehler ausgelöst wird zurückgegeben? In welchem ​​Teil versucht Hibernate, auf den LazyEntity zuzugreifen, weil, wie Sie im obigen Code sehen können, ich nicht versuche, innerhalb des API-Endpunkts zuzugreifen. Kann ich die Ausnahme abfangen?

Was kann ich tun, um das Objekt wie folgt zu erhalten, ohne die Ausnahme zu erhalten? Ich habe bereits gesehen, dass ich es deaktivieren kann, indem Sie die Eigenschaft hibernate.enable_lazy_load_no_trans ändern. Aber ich auch read, dass dies nicht sehr zu empfehlen ist.

User { 
    id: 1, 
    lastChanged: 0981283812738, 
    creationDate: 2178371283098, 
    lazyEntity: null 
} 

Antwort

1

denke ich, das Problem in der Serialisierung zu JSON der getAll() -Methode zu UsersEndpoint ist (durch die Anmerkung über die Methode ausgelöst).

Ich nehme an, Sie verwenden Jersey + Jackson (das ist eine gemeinsame Java < -> JSON-Konverter).

Wenn die getAll() -Methode abgeschlossen ist, nehmen Jackson die Ergebnisse der Methode und versuchen, es in JSON zu konvertieren, indem alle Daten der Benutzerklasse abgerufen werden. Um dies zu tun, ruft Jackson getLazyEntity() in der User-Klasse auf und löst, da es lazy loaded ist, einen Datenbankzugriff aus (und scheitert, weil die Sitzung geschlossen ist).

Wenn Sie die Daten der "LazyEntity" in Ihrer JSON-Antwort haben möchten, müssen Sie die Daten vor dem Schließen der Sitzung abrufen: innerhalb der DAO mit einem Abruf Join in der HQL-Abfrage.

Wenn Sie nicht möchten, dass die LazyEntity im JSON, müssen Sie Jackson sagen, nicht die LazyEntity zu serialisieren, können Sie das mit einer Jackson-Ansicht tun. Siehe How can a @JsonView working with jersey und http://wiki.fasterxml.com/JacksonJsonViews.

+0

Vielen Dank für diese Erklärung. Aber ich kann die '@ JsonView' Annotation nicht finden. Gibt es eine andere Art und Weise? – user289520

+0

Okay, ich habe es verstanden. Aber anstelle von '@ JsonView' habe ich' @ JsonIgnore' verwendet. Ich denke, das ist viel weniger Code oder würden Sie nicht zustimmen? – user289520

+0

Ich stimme zu, dass '@ JsonView' mühsam ist. Sein Vorteil besteht darin, dass ein Attribut mehreren @ JsonView zugeordnet werden kann, die einige Endpunkte haben, die alle Attribute des Objekts serialisieren, und andere Endpunkte, die nur einen Teil des Objekts serialisieren. – PCO