So beheben Sie Hibernate LazyInitializationException: Fehler beim Initialisieren einer Rollensammlung, Proxy konnte nicht initialisiert werden - keine Sitzung

102

Im benutzerdefinierten AuthenticationProvider aus meinem Frühjahrsprojekt versuche ich, die Liste der Berechtigungen des angemeldeten Benutzers zu lesen, aber es tritt der folgende Fehler auf:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.horariolivre.entity.Usuario.autorizacoes, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266)
    at com.horariolivre.security.CustomAuthenticationProvider.authenticate(CustomAuthenticationProvider.java:45)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

Wenn ich andere Themen von hier in StackOverflow lese, verstehe ich, dass dies aufgrund der Art und Weise geschieht, wie diese Art von Attribut vom Framework behandelt wird, aber ich kann keine Lösung für meinen Fall finden. Jemand kann zeigen, was ich falsch mache und was ich tun kann, um es zu beheben?

Der Code meines benutzerdefinierten Authentifizierungsanbieters lautet:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UsuarioHome usuario;

    public CustomAuthenticationProvider() {
        super();
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("CustomAuthenticationProvider.authenticate");

        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        Usuario user = usuario.findByUsername(username);

        if (user != null) {
            if(user.getSenha().equals(password)) {
                List<AutorizacoesUsuario> list = user.getAutorizacoes();

                List <String> rolesAsList = new ArrayList<String>();
                for(AutorizacoesUsuario role : list){
                    rolesAsList.add(role.getAutorizacoes().getNome());
                }

                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                for (String role_name : rolesAsList) {
                    authorities.add(new SimpleGrantedAuthority(role_name));
                }

                Authentication auth = new UsernamePasswordAuthenticationToken(username, password, authorities);
                return auth;
            }
            else {
                return null;
            }
        } else {
            return null;
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}

Meine Entitätsklassen sind:

UsuarioHome.java

@Entity
@Table(name = "usuario")
public class Usuario implements java.io.Serializable {

    private int id;
    private String login;
    private String senha;
    private String primeiroNome;
    private String ultimoNome;
    private List<TipoUsuario> tipoUsuarios = new ArrayList<TipoUsuario>();
    private List<AutorizacoesUsuario> autorizacoes = new ArrayList<AutorizacoesUsuario>();
    private List<DadosUsuario> dadosUsuarios = new ArrayList<DadosUsuario>();
    private ConfigHorarioLivre config;

    public Usuario() {
    }

    public Usuario(String login, String senha) {
        this.login = login;
        this.senha = senha;
    }

    public Usuario(String login, String senha, String primeiroNome, String ultimoNome, List<TipoUsuario> tipoUsuarios, List<AutorizacoesUsuario> autorizacoesUsuarios, List<DadosUsuario> dadosUsuarios, ConfigHorarioLivre config) {
        this.login = login;
        this.senha = senha;
        this.primeiroNome = primeiroNome;
        this.ultimoNome = ultimoNome;
        this.tipoUsuarios = tipoUsuarios;
        this.autorizacoes = autorizacoesUsuarios;
        this.dadosUsuarios = dadosUsuarios;
        this.config = config;
    }

    public Usuario(String login, String senha, String primeiroNome, String ultimoNome, String tipoUsuario, String[] campos) {
        this.login = login;
        this.senha = senha;
        this.primeiroNome = primeiroNome;
        this.ultimoNome = ultimoNome;
        this.tipoUsuarios.add(new TipoUsuario(this, new Tipo(tipoUsuario)));
        for(int i=0; i<campos.length; i++)
            this.dadosUsuarios.add(new DadosUsuario(this, null, campos[i]));
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "login", nullable = false, length = 16)
    public String getLogin() {
        return this.login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    @Column(name = "senha", nullable = false)
    public String getSenha() {
        return this.senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    @Column(name = "primeiro_nome", length = 32)
    public String getPrimeiroNome() {
        return this.primeiroNome;
    }

    public void setPrimeiroNome(String primeiroNome) {
        this.primeiroNome = primeiroNome;
    }

    @Column(name = "ultimo_nome", length = 32)
    public String getUltimoNome() {
        return this.ultimoNome;
    }

    public void setUltimoNome(String ultimoNome) {
        this.ultimoNome = ultimoNome;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "tipo_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_tipo") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<TipoUsuario> getTipoUsuarios() {
        return this.tipoUsuarios;
    }

    public void setTipoUsuarios(List<TipoUsuario> tipoUsuarios) {
        this.tipoUsuarios = tipoUsuarios;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "autorizacoes_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_autorizacoes") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<AutorizacoesUsuario> getAutorizacoes() {
        return this.autorizacoes;
    }

    public void setAutorizacoes(List<AutorizacoesUsuario> autorizacoes) {
        this.autorizacoes = autorizacoes;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "dados_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_dados") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<DadosUsuario> getDadosUsuarios() {
        return this.dadosUsuarios;
    }

    public void setDadosUsuarios(List<DadosUsuario> dadosUsuarios) {
        this.dadosUsuarios = dadosUsuarios;
    }

    @OneToOne
    @JoinColumn(name="fk_config")
    public ConfigHorarioLivre getConfig() {
        return config;
    }

    public void setConfig(ConfigHorarioLivre config) {
        this.config = config;
    }
}

AutorizacoesUsuario.java

@Entity
@Table(name = "autorizacoes_usuario", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class AutorizacoesUsuario implements java.io.Serializable {

    private int id;
    private Usuario usuario;
    private Autorizacoes autorizacoes;

    public AutorizacoesUsuario() {
    }

    public AutorizacoesUsuario(Usuario usuario, Autorizacoes autorizacoes) {
        this.usuario = usuario;
        this.autorizacoes = autorizacoes;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @OneToOne
    @JoinColumn(name = "fk_usuario", nullable = false, insertable = false, updatable = false)
    public Usuario getUsuario() {
        return this.usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    @OneToOne
    @JoinColumn(name = "fk_autorizacoes", nullable = false, insertable = false, updatable = false)
    public Autorizacoes getAutorizacoes() {
        return this.autorizacoes;
    }

    public void setAutorizacoes(Autorizacoes autorizacoes) {
        this.autorizacoes = autorizacoes;
    }

}

Autorizacoes.java

@Entity
@Table(name = "autorizacoes")
public class Autorizacoes implements java.io.Serializable {

    private int id;
    private String nome;
    private String descricao;

    public Autorizacoes() {
    }

    public Autorizacoes(String nome) {
        this.nome = nome;
    }

    public Autorizacoes(String nome, String descricao) {
        this.nome = nome;
        this.descricao = descricao;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "nome", nullable = false, length = 16)
    public String getNome() {
        return this.nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Column(name = "descricao", length = 140)
    public String getDescricao() {
        return this.descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
}

Vollständiges Projekt auf Github verfügbar

-> https://github.com/klebermo/webapp_horario_livre

Kleber Mota
quelle
Rufen Sie Ihre Behörden eifrig ab oder verwenden Sie einen OpenSessionInViewFilter.
Bart
Es ist genau das, was ich versuche zu sehen, wie es geht. Was ich versucht habe, war Folgendes : Liste <Autorizacoes> Authority = user.getAutorizacoes () , innerhalb derselben Funktion aus der Zuweisung von UsernamePasswordAuthenticationToken, aber immer noch nicht funktioniert.
Kleber Mota
2
@ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
Bart
Ok, das versuche ich, aber es funktioniert immer noch nicht. Meine Entitätsklasse aktualisiert: github.com/klebermo/webapp_horario_livre/blob/master/src/com/… , Mein aktueller Authentifizierungsanbieter: github.com/klebermo/webapp_horario_livre/blob/master/src/com/…
Kleber Mota

Antworten:

134

Sie müssen entweder fetch=FetchType.EAGERin Ihren ManyToMany-Anmerkungen hinzufügen, um untergeordnete Entitäten automatisch zurückzuziehen:

@ManyToMany(fetch = FetchType.EAGER)

Eine bessere Option wäre die Implementierung eines Spring Transaction Manager, indem Sie Ihrer Spring-Konfigurationsdatei Folgendes hinzufügen:

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

Anschließend können Sie Ihrer Authentifizierungsmethode eine @ Transactional-Annotation hinzufügen:

@Transactional
public Authentication authenticate(Authentication authentication)

Dadurch wird eine Datenbanktransaktion für die Dauer der Authentifizierungsmethode gestartet, sodass jede verzögerte Sammlung aus der Datenbank abgerufen werden kann, wenn Sie versuchen, sie zu verwenden.

jcmwright80
quelle
1
Tatsächlich habe ich den transactionManager in meiner Anwendung konfiguriert und verwende ihn in meinen DAO-Klassen. Wenn ich versuche, die von AuthenticationProvider authentifizierte Methode wie von Ihnen vorgeschlagen zu verwenden, wird eine Fehlermeldung angezeigt. Ursache: java.lang.IllegalArgumentException: Das Feld com.horariolivre.security.CustomAuthenticationProvider com.horariolivre.security.SecurityConfig.authenticationProvider kann nicht auf $ Proxy gesetzt werden . Ich erhalte den gleichen Fehler, wenn ich in meiner ManyToMany-Annotation add fetchType = FetchType.EAGER verwende (und ich kann dies nur in einem Attribut verwenden - ich habe drei gleiche Arten in meiner Entitätsklasse Usuario).
Kleber Mota
3
Nun, Sie müssen die untergeordneten Entitäten durchlaufen, die Sie in einer Transaktion verwenden möchten, um die LazyInitializationException zu vermeiden. Da sich Ihre Transaktionsanmerkung bei einer generischen Methode auf Dao-Ebene befindet, möchten Sie dies dort wahrscheinlich nicht tun. Daher müssen Sie vor dem Dao eine Serviceklasse implementieren, die die @ Transaktionsgrenzen aufweist, von denen aus Sie die gewünschte
untergeordnete
Protip für jemanden, der dies für die Zukunft erlebt; @Transaction muss auf einer öffentlichen Methode sein. Wenn dies nicht der Fall ist, funktioniert dies nicht. Möglicherweise sind Warnungen vorhanden oder nicht.
Nicolas
Ich habe
33

Der beste Weg, dies zu handhaben,LazyInitializationException besteht darin, die JOIN FETCHDirektive für alle Entitäten zu verwenden, die Sie abrufen müssen.

Verwenden Sie auf keinen Fall die folgenden Anti-Patterns, wie in einigen Antworten vorgeschlagen:

Manchmal ist eine DTO-Projektion die bessere Wahl als das Abrufen von Entitäten, und auf diese Weise erhalten Sie keine LazyInitializationException.

Vlad Mihalcea
quelle
1
Fetch Join ist gleichbedeutend mit eifrigem Abrufen. Was möglicherweise nicht immer machbar oder effizient ist. Auch das übliche Abrufen von Objekten erfolgt nicht über JPQL-Abfragen. Die Tatsache, dass es sich bei der offenen Sitzung um ein Antimuster handelt, ist ein langer Schuß, und ehrlich gesagt bin ich anderer Meinung. Es sollte natürlich mit Vorsicht verwendet werden, aber es gibt viele sehr gute Anwendungsfälle, die davon profitieren.
fer.marino
4
Nein, das ist es NICHT . Open Session in View ist ein Hack und ein Zeichen dafür, dass Entitäten auch für schreibgeschützte Projektionen abgerufen werden. Es gibt nicht viele perfekte Anwendungsfälle, die davon profitieren , egal wie sehr Sie versuchen werden, dies zu rechtfertigen. Es gibt keine Entschuldigung dafür, mehr Daten abzurufen, als Sie wirklich benötigen, und es gibt keine Entschuldigung dafür, Daten zu verlieren, die außerhalb der Grenzen der Transaktionsdienstschicht abgerufen werden.
Vlad Mihalcea
HI Vlad, können Sie bitte erklären, warum FETCH JOIN nicht gleichbedeutend mit eifrigem Laden ist. Ich gehe diesen Artikel durch: blog.arnoldgalovics.com/2017/02/27/… . Und es heißt: "Eine bessere Idee ist es, die Beziehung zum Zeitpunkt des Ladens der übergeordneten Entität zu laden. Dies kann mit einem Fetch Join erfolgen." Es ist also ein eifriges Laden. Ist es nicht?
Geek
1
Eifriges Führen bedeutet FetchType.EAGER, Ihre Assoziationen zu erweitern. JOIN FETCH ist für FetchType.LAZYAssoziationen gedacht , die zur Abfragezeit eifrig abgerufen werden müssen.
Vlad Mihalcea
25

Das Hinzufügen der folgenden Eigenschaft zu Ihrer persistence.xml kann Ihr Problem vorübergehend lösen

<property name="hibernate.enable_lazy_load_no_trans" value="true" />

Wie @ vlad-mihalcea sagte, ist es ein Antimuster und löst das Problem der verzögerten Initialisierung nicht vollständig. Initialisieren Sie Ihre Zuordnungen, bevor Sie die Transaktion abschließen, und verwenden Sie stattdessen DTOs.

Mohammad-Hossein Jamali
quelle
16

Ich hatte auch dieses Problem, als ich Unit-Tests durchführte. Eine sehr einfache Lösung für dieses Problem ist die Verwendung der Annotation @Transactional , die die Sitzung bis zum Ende der Ausführung geöffnet hält.

KarthikaSrinivasan
quelle
Verwenden Sie Hibernate Transational oder JPA Transactional?
jDub9
1
Ich habe Hibernate
KarthikaSrinivasan
11

Der Grund dafür ist, dass die Sitzung geschlossen wird, wenn Sie Lazy Load verwenden.

Es gibt zwei Lösungen.

  1. Verwenden Sie keine träge Ladung.

    In lazy=falseXML oder @OneToMany(fetch = FetchType.EAGER)In Annotation festlegen.

  2. Verwenden Sie Lazy Load.

    In lazy=trueXML oder @OneToMany(fetch = FetchType.LAZY)In Annotation festlegen.

    und fügen Sie OpenSessionInViewFilter filterin Ihreweb.xml

Detail Siehe meinen Beitrag.

https://stackoverflow.com/a/27286187/1808417

saneryee
quelle
1
OpenSessionInViewFilter ist auch ein Anti-Pattern. Ich schlage außerdem vor, niemals eine Zuordnung zu EAGER festzulegen, da es viele Fälle gibt, in denen Sie diese Daten nicht in der EAGER-Sammlung benötigen und Sie viel mehr Daten abrufen, als diese Anwendungsfälle benötigen, und Ihre Leistung erheblich reduzieren. Bitte behalten Sie alle Zuordnungen LAZY bei und fügen Sie stattdessen Join-Abrufe zu Ihren Abfragen hinzu.
user1567291
6

Sie können den Lazy-Initializer für den Ruhezustand verwenden.

Unten finden Sie den Code, auf den Sie verweisen können.
Hier PPIDOist das Datenobjekt, das ich abrufen möchte

Hibernate.initialize(ppiDO);
if (ppiDO instanceof HibernateProxy) {
    ppiDO = (PolicyProductInsuredDO) ((HibernateProxy) ppiDO).getHibernateLazyInitializer()
        .getImplementation();
    ppiDO.setParentGuidObj(policyDO.getBasePlan());
    saveppiDO.add(ppiDO);
    proxyFl = true;
}
Mitesh C.
quelle
6

Ihre benutzerdefinierte AuthenticationProvider-Klasse sollte mit folgenden Anmerkungen versehen sein:

@Transactional

Dadurch wird sichergestellt, dass auch dort die Ruhezustandssitzung vorhanden ist.

Bilal Ahmed Yaseen
quelle
4

Für diejenigen, die dieses Problem mit der Sammlung von Aufzählungen haben, ist hier, wie man es löst:

@Enumerated(EnumType.STRING)
@Column(name = "OPTION")
@CollectionTable(name = "MY_ENTITY_MY_OPTION")
@ElementCollection(targetClass = MyOptionEnum.class, fetch = EAGER)
Collection<MyOptionEnum> options;
Sasha Shpota
quelle
Das funktioniert bei mir. Ich habe auch die Option zum Hinzufügen von @Transactional getestet und es funktioniert auch. Aber ich wähle diese Option.
Rick Dana
2

Zunächst möchte ich sagen, dass alle Benutzer, die über Faulheit und Transaktionen gesprochen haben, Recht hatten. In meinem Fall gab es jedoch einen kleinen Unterschied darin, dass ich das Ergebnis der @ Transactional- Methode in einem Test verwendet habe und dass dies außerhalb der tatsächlichen Transaktion lag, sodass ich diese faule Ausnahme bekam.

Meine Servicemethode:

@Transactional
User get(String uid) {};

Mein Testcode:

User user = userService.get("123");
user.getActors(); //org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role

Meine Lösung bestand darin, diesen Code in eine andere Transaktion wie diese zu verpacken:

List<Actor> actors = new ArrayList<>();
transactionTemplate.execute((status) 
 -> actors.addAll(userService.get("123").getActors()));
vk23
quelle
1

Ich glaube, anstatt eifriges Abrufen zu ermöglichen, ist es sinnvoll, Ihre Entität dort neu zu initialisieren, wo es erforderlich ist, um LazyInitializationExceptionAusnahmen zu vermeiden

Hibernate.initialize(your entity);
Pravin
quelle
0

Wenn Sie JaVers verwenden und eine geprüfte Entitätsklasse angeben , möchten Sie möglicherweise die Eigenschaften ignorieren, die die LazyInitializationExceptionAusnahme verursachen (z. B. mithilfe der @DiffIgnoreAnmerkung).

Dies weist das Framework an, diese Eigenschaften bei der Berechnung der Objektunterschiede zu ignorieren, damit nicht versucht wird, die zugehörigen Objekte außerhalb des Transaktionsbereichs aus der Datenbank zu lesen (wodurch die Ausnahme verursacht wird).

Nickshoe
quelle
0

Es ist üblich, eine @Transactionalüber Ihre Serviceklasse zu stellen.

@Service
@Transactional
public class MyServiceImpl implements MyService{
...
}
Deb
quelle
-1

Fügen Sie die Anmerkung hinzu

@JsonManagedReference

Zum Beispiel:

@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "autorizacoes_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_autorizacoes") })
@JsonManagedReference
public List<AutorizacoesUsuario> getAutorizacoes() {
    return this.autorizacoes;
}
Mauricio
quelle