with tutorial mvc example ejemplo java spring hibernate spring-mvc spring-security

java - tutorial - LazyInitializationException: no se pudo inicializar de forma diferida una colección de roles, no se pudo inicializar el proxy-sin Session



spring security ejemplo (9)

Agrega la anotación

@JsonManagedReference

Por ejemplo:

@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; }

En el AuthenticationProvider personalizado de mi proyecto de primavera, estoy intentando leer la lista de autoridades del usuario registrado, pero me enfrenta el siguiente error:

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)

Al leer otros temas desde aquí en StackOberflow, entiendo que esto sucede debido a la forma en que este tipo de atributo es manejado por el marco, pero no puedo encontrar ninguna solución para mi caso. ¿Alguien puede señalar lo que estoy haciendo mal y qué puedo hacer para solucionarlo?

El código de mi Custom AuthenticationProvider es:

@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); } }

Mis clases de Entidad son:

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; } }

Proyecto completo disponible en github

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


Creo que en lugar de habilitar la búsqueda ansiosa, tiene sentido reiniciar su entidad cuando sea necesario para evitar la excepción LazyInitializationException

Hibernate.initialize(your entity);


En primer lugar, me gustaría decir que todos los usuarios que dijeron sobre flojo y transacciones tenían razón. Pero en mi caso había una ligera diferencia en que utilicé el resultado del método @Transactional en una prueba y eso estaba fuera de la transacción real, así que obtuve esta excepción.

Mi método de servicio:

@Transactional User get(String uid) {};

Mi código de prueba:

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

Mi solución a esto fue envolver ese código en otra transacción como esta:

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


La razón es que cuando usa carga diferida, la sesión se cierra.

Hay dos soluciones.

  1. No use la carga lenta.

    Establezca lazy=false en XML o Set @OneToMany(fetch = FetchType.EAGER) En la anotación.

  2. Usa carga lenta

    Establezca lazy=true en XML o Set @OneToMany(fetch = FetchType.LAZY) En la anotación.

    y agrega el OpenSessionInViewFilter filter en tu web.xml

Detalle Ver mi publicación.

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


Necesita agregar fetchType = FetchType.EAGER dentro de sus anotaciones ManyToMany para retirar automáticamente entidades secundarias, una mejor opción sería implementar SpringManageManager agregando lo siguiente a su archivo de configuración de primavera:

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven />

A continuación, puede agregar una anotación @Transactional a su método de autentificación así:

@Transactional public Authentication authenticate(Authentication authentication)

Esto iniciará una transacción db durante el método de autenticación que permite recuperar cualquier colección diferida de la base de datos cuando intente utilizarlas.


Puede usar el inicializador perezoso de hibernación.

A continuación se muestra el código que puede consultar.
Aquí PPIDO es el objeto de datos que quiero recuperar

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


Yo también tuve este problema cuando estaba haciendo pruebas unitarias. Una solución muy simple a este problema es usar la anotación @Transactional que mantiene la sesión abierta hasta el final de la ejecución.


agregue esto a su persistence.xml

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