Olá a todos, tudo bem?
Estou com um problema para formular uma pesquisa utilizando Criteria.
Tenho as seguintes classes:
User
@Entity
@Table(name="user")
public class User implements Serializable, UserDetails {
private static final long serialVersionUID = -8451679170281063697L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
@ManyToMany(cascade={ CascadeType.ALL, CascadeType.MERGE })
@JoinTable(name="user_cargo",
joinColumns = @JoinColumn(name="user_id" , referencedColumnName="id"),
inverseJoinColumns = @JoinColumn(name="cargos_id" , referencedColumnName="id"))
private List<Cargo> cargos;
...
Cargo
@Entity
@Table(name="cargo")
public class Cargo implements Serializable {
private static final long serialVersionUID = 1886820991361556707L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
private String nome;
...
Quando o Hibernate mapeia estas classes ele cria a tabela no banco user_cargo com as colunas user_id e cargos_id.
Minha dúvida: a partir do id do usuário preciso consultar e retornar uma lista de nomes do(s) cargo(s) que o User possui.
Usando o SQL consigo fazendo assim:
select cargo.nome from cargo inner join user_cargo where user_id = ?;
Alguém tem ideia de como ficaria usando Criteria?
Meu método atual, conforme abaixo, esta errado. Ele compara o id do usuário diretamente com id dos cargos, não passando por essa tabela user_cargo que o Hibernate criou.
public Cargo buscarCargoPorId(long id){
if (!session.isOpen()) {
session = sessionFactory.openSession();
}
Criteria criteria = session.createCriteria(Cargo.class);
criteria.add(Restrictions.eq("id",id));
Cargo cargo = (Cargo) criteria.uniqueResult();
if (session.isOpen()) {
session.close();
}
return cargo;
}
Muito obrigado.
Abraços.
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.idEq(idDoUsuario);
User u = (User) criteria.uniqueResult();
List<Cargo> cargos = u.getCargos();
Obrigado pela ajuda drsmachado mas, a princípio, não subiu. Segue erro do Tomcat:
HTTP Status 500 - failed to lazily initialize a collection of role: br.com.springsecurity.model.User.cargos, could not initialize proxy - no Session
type Exception report
message failed to lazily initialize a collection of role: br.com.springsecurity.model.User.cargos, could not initialize proxy - no Session
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: failed to lazily initialize a collection of role: br.com.springsecurity.model.User.cargos, could not initialize proxy - no Session
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:150)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.springsecurity.model.User.cargos, could not initialize proxy - no Session
org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:137)
org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:242)
javax.faces.model.ListDataModel.isRowAvailable(ListDataModel.java:110)
javax.faces.model.ListDataModel.setRowIndex(ListDataModel.java:185)
javax.faces.model.ListDataModel.setWrappedData(ListDataModel.java:220)
javax.faces.model.ListDataModel.<init>(ListDataModel.java:79)
javax.faces.component.UIData.getDataModel(UIData.java:1804)
javax.faces.component.UIData.setRowIndexWithoutRowStatePreserved(UIData.java:484)
javax.faces.component.UIData.setRowIndex(UIData.java:473)
com.sun.faces.renderkit.html_basic.TableRenderer.encodeBegin(TableRenderer.java:81)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:820)
javax.faces.component.UIData.encodeBegin(UIData.java:1118)
com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
com.sun.faces.renderkit.html_basic.TableRenderer.renderRow(TableRenderer.java:384)
com.sun.faces.renderkit.html_basic.TableRenderer.encodeChildren(TableRenderer.java:161)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:401)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:150)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.40 logs.
Apache Tomcat/7.0.40
Segue método ajustado conforme indicação:
public List buscarCargoPorId(long id){
if (!session.isOpen()) {
session = sessionFactory.openSession();
}
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.idEq(id));
User user = (User) criteria.uniqueResult();
List<Cargo> cargo = user.getCargos();
if (session.isOpen()) {
session.close();
}
return cargo;
}
Abraços.
O que está acontecendo é que cargos está como LAZY, que é o padrão do fetch.
Sendo assim, quando você tenta realizar a chamada ao método getCargos, um novo select será feito.
Por alguma razão, a sessão está sendo fechada.
Não sei se cargos é a única coleção na classe User, se for, você pode colocar o fetch como EAGER e resolver isso. Se não for, você terá de pesquisar alguma forma de gerenciar a sessão.
Obrigado pela ajuda drsmachado.
Realmente tenho mais coleções dentro da classe User e o hibernate só aceita um fetch EAGER.
Vou ter que procurar sobre esta questão do gerenciamento de sessão.
Caso alguém tenha outra sugestão?!?!
Abraços.
Procure aqui. Provavelmente você vai achar algo (embora aborde JPA, serve para o hibernate).
Acredito não ser uma boa prática de programação, mas apenas tirei as linhas que fecham a sessão e deu certo. Lista tudo!
Vou ter que fechar a sessão na unha agora pra não ficar aberta a toa. A questão é: até onde, deixar esta sessão usada na pesquisa aberta, afeta o desempenho da aplicação? Vou ter em média 50 a 80 acessos simultâneos.
Obrigado pela ajuda!
[quote=alain_oliveira]Acredito não ser uma boa prática de programação, mas apenas tirei as linhas que fecham a sessão e deu certo. Lista tudo!
Vou ter que fechar a sessão na unha agora pra não ficar aberta a toa. A questão é: até onde, deixar esta sessão usada na pesquisa aberta, afeta o desempenho da aplicação? Vou ter em média 50 a 80 acessos simultâneos.
Obrigado pela ajuda![/quote]
Sé é aplicação web abre a session antes de processar a requisição e fecha a session após sair dela. Pesquisa sobre OpenSessionInView + hibernate.
[quote=javaflex][quote=alain_oliveira]Acredito não ser uma boa prática de programação, mas apenas tirei as linhas que fecham a sessão e deu certo. Lista tudo!
Vou ter que fechar a sessão na unha agora pra não ficar aberta a toa. A questão é: até onde, deixar esta sessão usada na pesquisa aberta, afeta o desempenho da aplicação? Vou ter em média 50 a 80 acessos simultâneos.
Obrigado pela ajuda![/quote]
Sé é aplicação web abre a session antes de processar a requisição e fecha a session após sair dela. Pesquisa sobre OpenSessionInView + hibernate.[/quote]
Excelente dica. Acho que vai resolver o problema. Muito obrigado.