Come risolvere l'eccezione Hibernate "impossibile inizializzare pigramente una raccolta di ruoli"


363

Ho questo problema:

org.hibernate.LazyInitializationException: impossibile inizializzare pigramente una raccolta di ruoli: mvc3.model.Topic.comments, nessuna sessione o sessione è stata chiusa

Ecco il modello:

@Entity
@Table(name = "T_TOPIC")
public class Topic {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @ManyToOne
    @JoinColumn(name="USER_ID")
    private User author;

    @Enumerated(EnumType.STRING)    
    private Tag topicTag;

    private String name;
    private String text;

    @OneToMany(mappedBy = "topic", cascade = CascadeType.ALL)
    private Collection<Comment> comments = new LinkedHashSet<Comment>();

    ...

    public Collection<Comment> getComments() {
           return comments;
    }

}

Il controller, che chiama il modello, è simile al seguente:

@Controller
@RequestMapping(value = "/topic")
public class TopicController {

    @Autowired
    private TopicService service;

    private static final Logger logger = LoggerFactory.getLogger(TopicController.class);


    @RequestMapping(value = "/details/{topicId}", method = RequestMethod.GET)
    public ModelAndView details(@PathVariable(value="topicId") int id)
    {

            Topic topicById = service.findTopicByID(id);
            Collection<Comment> commentList = topicById.getComments();

            Hashtable modelData = new Hashtable();
            modelData.put("topic", topicById);
            modelData.put("commentList", commentList);

            return new ModelAndView("/topic/details", modelData);

     }

}

La pagina jsp ha il seguente aspetto:

<%@page import="com.epam.mvc3.helpers.Utils"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
      <title>View Topic</title>
</head>
<body>

<ul>
<c:forEach items="${commentList}" var="item">
<jsp:useBean id="item" type="mvc3.model.Comment"/>
<li>${item.getText()}</li>

</c:forEach>
</ul>
</body>
</html>

L'eccezione è aumentata quando si visualizza jsp. In linea con c: forOach loop

Risposte:


214

Se sai che vorrai vedere tutti Commenti messaggi ogni volta che lo recuperi, Topicmodifica la mappatura dei campi per comments:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)
private Collection<Comment> comments = new LinkedHashSet<Comment>();

Le raccolte sono caricate di default per impostazione predefinita, dai un'occhiata a questo se vuoi saperne di più.


35
Mi dispiace, ma vorrei usare lazy-load. Quindi, ho cambiato il tipo 'LinkedHashSet' in 'PersistentList'. Si verifica ancora un'eccezione
Eugene,

242
Questo potrebbe essere usato come soluzione alternativa, ma non come soluzione effettiva al problema. E se avessimo bisogno di recuperare pigramente?
Dkyc,

14
ma nel caso in cui desideriamo essere pigri, questa soluzione non funzionerà e nella maggior parte dei casi desideriamo solo essere pigri.
prashant thakre,

103
Questo è il tipo di risposta che compare ovunque in overflow dello stack. Corto, al punto, risolve il problema e MISLEADING. Ai futuri lettori, fatevi un favore e imparate cosa è esattamente pigro e preso con entusiasmo, e comprendete le conseguenze.
Ced

13
@darrengorman Quando ho avviato l'APP ho pubblicato una domanda attorno a quella di OP. Ho ricevuto la stessa risposta che mi hai dato. Abbastanza presto quando ho eseguito alcuni test con centinaia di migliaia di file, indovina cosa è successo? Penso che sia fuorviante perché fornisce una risposta troppo semplice per un problema che la maggior parte dei principianti dovrà affrontare e presto avranno il loro intero database caricato in memoria se non stanno attenti (e non lo faranno, perché non lo faranno esserne consapevole) :).
Ced

182

Dalla mia esperienza, ho i seguenti metodi per risolvere il famoso LazyInitializationException:

(1) Usa Hibernate.initialize

Hibernate.initialize(topics.getComments());

(2) Utilizzare JOIN FETCH

È possibile utilizzare la sintassi JOIN FETCH in JPQL per recuperare esplicitamente la raccolta figlio. Questo è un po 'come il recupero di EAGER.

(3) Utilizzare OpenSessionInViewFilter

LazyInitializationException si verifica spesso nel livello vista. Se si utilizza Spring framework, è possibile utilizzare OpenSessionInViewFilter. Tuttavia, non ti consiglio di farlo. Potrebbe causare problemi di prestazioni se non utilizzato correttamente.


5
(1) ha funzionato perfettamente per me. Il mio caso: Hibernate.initialize (register.getVehicle (). GetOwner (). GetPerson (). GetAddress ());
Leonel Sanches da Silva,

6
Sembra che Hibernate.initialize non funziona con EntityManager
marionmaiden

8
Questa dovrebbe essere la risposta corretta. Ad esempio, nel mio progetto al lavoro non dovremmo esplicitamente utilizzare il recupero EAGER. Causa problemi in questo particolare sistema.
Steve Waters,

Sembra interessante ma la mancanza di documentazione da implementare in un altro caso ... potresti fornire qualche altro link o spiegazione su come implementare questa soluzione?
Pipo,

58

So che è una vecchia domanda, ma voglio aiutare. È possibile inserire l'annotazione transazionale sul metodo di servizio necessario, in questo caso findTopicByID (id) dovrebbe avere

@Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)

maggiori informazioni su questa annotazione sono disponibili qui

Informazioni sulle altre soluzioni:

fetch = FetchType.EAGER 

non è una buona pratica, dovrebbe essere usato SOLO se necessario.

Hibernate.initialize(topics.getComments());

L'inizializzatore di ibernazione lega le tue classi alla tecnologia di ibernazione. Se stai mirando ad essere flessibile non è una buona strada da percorrere.

Spero che sia d'aiuto


3
L'annotazione @Transactional ha funzionato per me, ma nota che Propagation.REQUIRED è l'impostazione predefinita, almeno in Spring Boot 1.4.2 (Spring 4.3).
ben3000,

4
Sì, lo è, ma ho pensato che potesse essere apprezzato per chiarire che si potrebbe effettivamente cambiare il parametro di propagazione
sarbuLopex

Non è @Transactionalsolo una cosa di primavera?
Campa,

@Campa sì lo è. Se si desidera gestirlo manualmente, è necessario inserire la propria logica aziendale all'interno di una transazione recuperata dal gestore entità
sarbuLopex

54

L'origine del tuo problema:

Per impostazione predefinita, l'ibernazione carica pigramente le raccolte (relazioni), il che significa che quando si utilizza il collectioncodice (qui commentscampo in Topicclasse) l'ibernazione lo ottiene dal database, ora il problema è che si sta ottenendo la raccolta nel controller (in cui la sessione JPA è chiuso). Questa è la riga di codice che causa l'eccezione (dove si sta caricando la commentsraccolta):

    Collection<Comment> commentList = topicById.getComments();

Stai ricevendo una raccolta di "commenti" (topic.getComments ()) nel controller (dove JPA sessionè terminata) e ciò causa l'eccezione. Inoltre, se avessi ottenuto la commentsraccolta nel tuo file jsp in questo modo (invece di averla nel tuo controller):

<c:forEach items="topic.comments" var="item">
//some code
</c:forEach>

Avresti comunque la stessa eccezione per lo stesso motivo.

Risolvere il problema:

Dato che puoi avere solo due raccolte con la FetchType.Eager(raccolta avidamente recuperata) in una classe Entity e poiché il caricamento lento è più efficiente del caricamento FetchTypeavido , penso che questo modo di risolvere il tuo problema sia meglio che cambiare semplicemente in desideroso:

Se si desidera inizializzare la raccolta pigra e anche farlo funzionare, è meglio aggiungere questo frammento di codice al proprio web.xml:

<filter>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Ciò che questo codice fa è che aumenterà la lunghezza della tua JPA sessiono come dice la documentazione, è usato in "to allow for lazy loading in web views despite the original transactions already being completed."questo modo la sessione JPA sarà aperta un po 'più a lungo e per questo motivo puoi caricare pigramente raccolte nei tuoi file jsp e nelle classi del controller .


7
Perché la sessione JPS è chiusa? Come evitare che venga chiuso? Come eseguire la raccolta pigra?
Dimmer

1
Cosa definisce un limite di due raccolte FetchType.Eager per Entità?
chrisinmtown,

In Spring Boot, puoi aggiungere "spring.jpa.open-in-view = true" a "application.properties"
Askar,

28

Il motivo è che quando si utilizza il caricamento lento, la sessione viene chiusa.

Esistono due soluzioni.

  1. Non usare il carico lento.

    Imposta lazy=falsein XML o Imposta @OneToMany(fetch = FetchType.EAGER)in annotazione.

  2. Usa un carico lento.

    Imposta lazy=truein XML o Imposta @OneToMany(fetch = FetchType.LAZY)in annotazione.

    e aggiungi il OpenSessionInViewFilter filtertuoweb.xml

Dettaglio Vedi il mio POST .


1
... eppure entrambe le soluzioni non sono buone. Suggerire di utilizzare EAGER può creare enormi problemi. L'uso di OpenSessionInViewFilter è un anti-pattern.
Rafael,

27
@Controller
@RequestMapping(value = "/topic")
@Transactional

risolvo questo problema aggiungendo @Transactional, penso che questo possa rendere aperta la sessione


Perché questo ha ricevuto un voto negativo? L'aggiunta di una transazione all'operazione estende la sessione
Tudor Grigoriu,

1
Non è buona pratica aggiungere @Transactional al controller.
Rafael,

@Rafael Perché è una brutta pratica?
Amr Ellafy il

@AmrEllafy -> Ecco una buona spiegazione: stackoverflow.com/a/18498834/1261162
Rafael

22

Il problema è causato dall'accesso a un attributo con la sessione di ibernazione chiusa. Non hai una transazione di ibernazione nel controller.

Possibili soluzioni:

  1. Esegui tutta questa logica, nel livello di servizio (con @Transactional), non nel controller. Dovrebbe esserci il posto giusto per farlo, fa parte della logica dell'app, non nel controller (in questo caso, un'interfaccia per caricare il modello). Tutte le operazioni nel livello di servizio devono essere transazionali. ovvero: spostare questa riga nel metodo TopicService.findTopicByID:

    Collection commentList = topicById.getComments ();

  2. Usa "desideroso" invece di "pigro" . Ora non stai usando 'pigro' .. non è una vera soluzione, se vuoi usare pigro, funziona come una soluzione temporanea (molto temporanea).

  3. utilizzare @Transactional nel controller . Non dovrebbe essere usato qui, stai mescolando il livello di servizio con la presentazione, non è un buon design.
  4. utilizzare OpenSessionInViewFilter , segnalati molti svantaggi, possibile instabilità.

In generale, la soluzione migliore è la 1.


2
Fetch tipo di Eager per scontato che Hibernate sarà tirato tutti i dati nella prima query, non tutti i luoghi è corretta
Жасулан Бердибеков

Dovresti MAI RENDERE CHE LA MIGLIORE SOLUZIONE È 1 ... in realtà è l'UNICA BUONA soluzione poiché tutti gli altri sono anti-pattern!
Rafael,

19

Per caricare in modo pigro una raccolta ci deve essere una sessione attiva. In un'app Web ci sono due modi per farlo. È possibile utilizzare il modello Apri sessione nella vista , in cui si utilizza un intercettore per aprire la sessione all'inizio della richiesta e chiuderla alla fine. Il rischio è che devi avere una solida gestione delle eccezioni o che potresti vincolare tutte le sessioni e la tua app potrebbe bloccarsi.

L'altro modo per gestirlo è quello di raccogliere tutti i dati necessari nel controller, chiudere la sessione e quindi inserire i dati nel modello. Personalmente preferisco questo approccio, in quanto sembra un po 'più vicino allo spirito del modello MVC. Inoltre, se si ottiene un errore dal database in questo modo, è possibile gestirlo molto meglio che se si verifica nel proprio renderer di visualizzazione. Il tuo amico in questo scenario è Hibernate.initialize (myTopic.getComments ()). Dovrai anche ricollegare l'oggetto alla sessione, poiché stai creando una nuova transazione con ogni richiesta. Usa session.lock (myTopic, LockMode.NONE) per questo.


15

Come ho spiegato in questo articolo , il modo migliore per gestirlo LazyInitializationExceptionè recuperarlo al momento della query, in questo modo:

select t
from Topic t
left join fetch t.comments

Dovresti SEMPRE evitare i seguenti anti-schemi:

Pertanto, assicurarsi che le FetchType.LAZYassociazioni siano inizializzate al momento della query o nell'ambito originale @Transactionalutilizzando Hibernate.initializeper raccolte secondarie.


1
Vlad, hai qualche suggerimento per lavorare con una raccolta inizializzata in modo pigro in un'entità recuperata dal metodo findById () di un repository generato da Spring? Non sto scrivendo la query e la transazione non rientra nel mio codice.
chrisinmtown,

Dai un'occhiata a questo articolo per maggiori dettagli sull'inizializzazione di raccolte pigre.
Vlad Mihalcea,

Potresti chiarire che cosa intendi con "all'interno dell'ambito @Transactional originale" Questo non mi è chiaro poiché sembra che si verifichi questo errore durante una sessione aperta (ma non quella giusta?)
Michiel Haisma,

All'interno dell'ambito del metodo di servizio transazionale più elevato, noto anche come gateway di transazione. Dai un'occhiata alla TrassctionInterceptortraccia nello stack e questo è quello.
Vlad Mihalcea,

Una delle migliori risposte di gran lunga ... questa dovrebbe essere contrassegnata come corretta. A proposito ... supponendo che OSIV sia un anti-pattern come è possibile che sia abilitato di default nelle versioni recenti con avvio a molla? ... forse non è poi così male?
Rafael,

10

Se stai cercando di avere una relazione tra un'entità e una Collezione o un Elenco di oggetti Java (ad esempio tipo Lungo), vorrebbe qualcosa del genere:

@ElementCollection(fetch = FetchType.EAGER)
    public List<Long> ids;

1
in molti casi, non vuoi davvero farlo.
Perdi

L'uso di EAGER non è una soluzione professionale.
Rafael,

9

Una delle migliori soluzioni è aggiungere quanto segue nel file application.properties: spring.jpa.properties.hibernate.enable_lazy_load_no_trans = true


1
Puoi dire all'OP cosa fa esattamente, eventuali effetti collaterali, impatto sulle prestazioni?
PeS

3
Sul retro del caricamento lento, una nuova sessione viene biforcuta ogni volta che un'associazione viene caricata pigramente, quindi vengono biforcute più connessioni e crea un po 'di pressione sul pool di connessioni. Se hai un limite al numero di connessioni, questa proprietà potrebbe non essere corretta da usare.
sreekmatta,

2
per alcuni, è considerato un vladmihalcea.com/
Uri Loya,

7

Ho scoperto che dichiarare @PersistenceContextcome EXTENDEDrisolve anche questo problema:

@PersistenceContext(type = PersistenceContextType.EXTENDED)

1
Ciao, stai attento con tali cambiamenti. La creazione del contesto di persistenza con ambito TRANSACTION è pigra, che era l'intento di OP. Quindi la domanda è se vuoi essere apolide o no. Questa impostazione dipende dallo scopo del sistema e non dovrebbe essere modificata troppo ... con impazienza. Se capisci cosa intendo. Leggi qui stackoverflow.com/questions/2547817/...
kiedysktos

Pericoloso. Questa non è la risposta corretta Ce ne sono altri molto più precisi e sicuri.
Rafael,

5

è stato il problema che ho affrontato di recente che ho risolto con l'utilizzo

<f:attribute name="collectionType" value="java.util.ArrayList" />

una descrizione più dettagliata qui e questo mi ha salvato la giornata.


5

il tuo elenco è in fase di caricamento lento, quindi l'elenco non è stato caricato. chiamare per entrare nell'elenco non è sufficiente. utilizzare in Hibernate.initialize per avviare l'elenco. Se dosnt funziona, esegui l'elemento dell'elenco e chiama Hibernate.initialize per ciascuno. questo deve essere prima di tornare dall'ambito della transazione. guarda questo post.
Cercare -

Node n = // .. get the node
Hibernate.initialize(n); // initializes 'parent' similar to getParent.
Hibernate.initialize(n.getChildren()); // pass the lazy collection into the session 

4

Per risolvere il problema nel mio caso mancava solo questa riga

<tx:annotation-driven transaction-manager="myTxManager" />

nel file di contesto dell'applicazione.

L' @Transactionalannotazione su un metodo non è stata presa in considerazione.

Spero che la risposta possa aiutare qualcuno


4

@ Manca l'annotazione transazionale sul controller

@Controller
@RequestMapping("/")
@Transactional
public class UserController {
}

17
Direi che la gestione delle transazioni appartiene al livello di servizio in cui risiede la logica aziendale.
Sõber,

L'annotazione transazionale non manca. Il controller non dovrebbe avere tale annotazione. Tali annotazioni dovrebbero essere a livello di servizio.
Rafael,

4

Utilizzando l' @Transactionalannotazione ibernazione , se si ottiene un oggetto dal database con attributi recuperati pigri, è possibile ottenerli semplicemente recuperando questi attributi in questo modo:

@Transactional
public void checkTicketSalePresence(UUID ticketUuid, UUID saleUuid) {
        Optional<Ticket> savedTicketOpt = ticketRepository.findById(ticketUuid);
        savedTicketOpt.ifPresent(ticket -> {
            Optional<Sale> saleOpt = ticket.getSales().stream().filter(sale -> sale.getUuid() == saleUuid).findFirst();
            assertThat(saleOpt).isPresent();
        });
}

Qui, in una transazione gestita dal proxy Hibernate, il fatto di chiamare ticket.getSales()fa un'altra query per recuperare le vendite perché l'hai esplicitamente richiesto.


4

Due cose che dovresti avere fetch = FetchType.LAZY.

@Transactional

e

Hibernate.initialize(topicById.getComments());

2

Per quelli che lavorano con Criteria , l'ho scoperto

criteria.setFetchMode("lazily_fetched_member", FetchMode.EAGER);

fatto tutto ciò di cui avevo bisogno.

La modalità di recupero iniziale per le raccolte è impostata su FetchMode.LAZY per fornire prestazioni, ma quando ho bisogno dei dati, aggiungo solo quella linea e mi godo gli oggetti completamente popolati.


2

Nel mio caso il seguente codice era un problema:

entityManager.detach(topicById);
topicById.getComments() // exception thrown

Perché si è staccato dal database e Hibernate non ha più recuperato l'elenco dal campo quando era necessario. Quindi lo inizializzo prima di staccare:

Hibernate.initialize(topicById.getComments());
entityManager.detach(topicById);
topicById.getComments() // works like a charm

1

Il motivo è che stai cercando di ottenere l'elenco dei commenti sul controller dopo aver chiuso la sessione all'interno del servizio.

topicById.getComments();

Sopra caricherà l'elenco dei commenti solo se la sessione di ibernazione è attiva, che immagino tu abbia chiuso al tuo servizio.

Quindi, devi ottenere l'elenco dei commenti prima di chiudere la sessione.


2
Sì, questa è la dichiarazione del problema. Dovresti anche fornire una risposta in unAnswer
Sarz

1

La raccolta commentsnella tua classe di modello Topicè caricata pigramente, che è il comportamento predefinito se non lo annoti fetch = FetchType.EAGERspecificatamente.

È molto probabile che il tuo findTopicByIDservizio stia utilizzando una sessione Hibernate senza stato. Una sessione senza stato non ha la cache di primo livello, ovvero nessun contesto di persistenza. Più tardi, quando si tenta di iterare comments, Hibernate genererà un'eccezione.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mvc3.model.Topic.comments, no session or session was closed

La soluzione può essere:

  1. Annota commentsconfetch = FetchType.EAGER

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)   
    private Collection<Comment> comments = new LinkedHashSet<Comment>();
  2. Se desideri comunque che i commenti vengano caricati pigramente, utilizza le sessioni stateful di Hibernate , in modo da poter recuperare i commenti in seguito su richiesta.


1

Nel mio caso, ho avuto la mappatura b / w Ae Bcome

A ha

@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
Set<B> bs;

nel DAOlivello, il metodo deve essere annotato @Transactionalse non si è annotato il mapping con Fetch Type - Eager


1

Non è la soluzione migliore, ma per coloro che si trovano ad affrontare LazyInitializationExceptionsoprattutto Serializationquesto aiuterà. Qui controllerai le proprietà pigramente inizializzate e l'impostazione nullsu quelle. Per questo creare la classe sottostante

public class RepositoryUtil {
    public static final boolean isCollectionInitialized(Collection<?> collection) {
        if (collection instanceof PersistentCollection)
            return ((PersistentCollection) collection).wasInitialized();
        else 
            return true;
    }   
}

All'interno della tua classe Entity di cui stai inizializzando pigramente aggiungi un metodo come mostrato di seguito. Aggiungi tutte le proprietà di caricamento pigramente all'interno di questo metodo.

public void checkLazyIntialzation() {
    if (!RepositoryUtil.isCollectionInitialized(yourlazyproperty)) {
        yourlazyproperty= null;
    }

Chiamare questo checkLazyIntialzation()metodo dopo in tutti i luoghi in cui si stanno caricando i dati.

 YourEntity obj= entityManager.find(YourEntity.class,1L);
  obj.checkLazyIntialzation();

0

Ciao Tutti i post abbastanza tardi spero che aiuti gli altri, ringraziando anticipatamente @GMK per questo post Hibernate.initialize (oggetto)

quando Lazy = "true"

Set<myObject> set=null;
hibernateSession.open
set=hibernateSession.getMyObjects();
hibernateSession.close();

ora, se accedo a 'set' dopo la chiusura della sessione, viene generata un'eccezione.

La mia soluzione:

Set<myObject> set=new HashSet<myObject>();
hibernateSession.open
set.addAll(hibernateSession.getMyObjects());
hibernateSession.close();

ora posso accedere a 'set' anche dopo aver chiuso la sessione di ibernazione.


0

Ancora un altro modo per fare ciò, è possibile utilizzare TransactionTemplate per avvolgere il recupero pigro. Piace

Collection<Comment> commentList = this.transactionTemplate.execute
(status -> topicById.getComments());

0

Il problema è causato dal fatto che il codice accede a una relazione JPA pigra quando la "connessione" al database viene chiusa (il contesto di persistenza è il nome corretto in termini di ibernazione / JPA).

Un modo semplice per risolverlo in Spring Boot consiste nel definire un livello di servizio e utilizzare l' @Transactionalannotazione. Questa annotazione in un metodo crea una transazione che si propaga nel livello del repository e mantiene aperto il contesto di persistenza fino al termine del metodo. Se si accede alla raccolta all'interno del metodo transazionale Hibernate / JPA recupererà i dati dal database.

Nel tuo caso, devi solo annotare con @Transactionalil metodo findTopicByID(id)nel tuo TopicServicee forzare il recupero della raccolta in quel metodo (ad esempio, chiedendone la dimensione):

    @Transactional(readOnly = true)
    public Topic findTopicById(Long id) {
        Topic topic = TopicRepository.findById(id).orElse(null);
        topic.getComments().size();
        return topic;
    }

0

Per eliminare l'eccezione di inizializzazione lazy non è necessario chiamare la raccolta lazy quando si opera con un oggetto distaccato.

Secondo la mia opinione, l'approccio migliore è usare DTO, e non entità. In questo caso è possibile impostare esplicitamente i campi che si desidera utilizzare. Come al solito è abbastanza. Non c'è bisogno di preoccuparsi che qualcosa come jackson ObjectMappero hashCodegenerato da Lombok chiamerà implicitamente i tuoi metodi.

Per alcuni casi specifici puoi utilizzare l' @EntityGrpaphannotazione, che ti consente di eagercaricare anche se hai fetchType=lazynella tua entità.


0

Esistono molteplici soluzioni per questo problema di Inizializzazione pigra:

1) Cambia il tipo di associazione Fetch da LAZY a EAGER ma questa non è una buona pratica perché ciò peggiorerà le prestazioni.

2) Utilizzare FetchType.LAZY sull'oggetto associato e utilizzare anche l'annotazione transazionale nel metodo del livello di servizio in modo che la sessione rimanga aperta e quando si chiamerà topicById.getComments (), l'oggetto figlio (commenti) verrà caricato.

3) Inoltre, prova a utilizzare l'oggetto DTO anziché l'entità nel livello controller. Nel tuo caso, la sessione è chiusa a livello di controller. COSÌ meglio convertire un'entità in DTO nel livello di servizio.


-11

ho risolto usando Elenco invece di Set:

private List<Categories> children = new ArrayList<Categories>();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.