Alternativa ao Open Session In View?

2 respostas
R

Tenho outro pattern de programação que possa substituir o Open Session in View?

Assim, quero deixar alguns relacionamentos Lazy, porém como estou fechando e abrindo sempre as sessões da erro de LazyInitializationException.

Teria que implementar o Open Session in View, porém seleciono o banco apenas em runtime, então não tenho como passar isso na servlet. (já que ela é inicializada junto com o Tomcat)

Tenho alguma alternativa?

2 Respostas

Paulo_Silveira

Ola Rafael!

Da sim pra fazer o open session in view com isso… basta voce abrir a session factory so depois de descobrir qual é o seu banco de dados, ai, a cada requisicao (atraves de um filter), abre e fecha a session, comitando antes de redirecionar ao jsp (dispatch).

abraços

R

Obrigado Paulo pelo esclarecimento.

Sabendo que era possível, fui atrás de informações e após umas 2 horas consegui (acho que está certo, já que não está mais pegando a exceção :D) implementar esse modelo do Open Session in View que evita ocorrer a LazyInitializationException.

Foi mais fácil do que pensei:

Utilizei esse link da documentaçao: (um dos poucos uteis que achei nesse assunto)
http://community.jboss.org/wiki/OpenSessioninView

Precisei fazer algumas modificações no Interceptador, e também fiz algumas observações que podem ajudar se alguém voltar nesse tópico:

-Ao realizar o login no sistema o usuário coloca um ID (que identifica de qual banco de dados criar a factory) na sessão.No interceptador eu só crio a factory quando já tiver a id na sessão.
-Também, observei que preciso colocar o chain.doFilter no else, pois se não chamar ele o processo não termina.Ele "trava", não tem prosseguimento.
-Outro detalhe, antes do commit na transação precisei colocar uma verificação que ela está ativa, para evitar o erro TransactionException

public class HibernateSessionRequestFilter implements Filter {
 
    private SessionFactory sf;
    private HttpSession session;
    
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException {
 
        try {
        	
        	//faço um cast, pois a servlet request não possui o get session
        	//e na assinatura no método me obriga a receber parametros do tipo ServletRequest
        	HttpServletRequest req = (HttpServletRequest) request;
        	
        	//só vou só vou realizar as ações caso já exista ID definido
        	if(req.getSession().getAttribute("id") != null){

        		//só vou criar a factory se ela ainda não foi criada
        		if(sf == null){
        			sf = HibernateUtil.getSessionFactory(req.getSession().getAttribute("id").toString());
        		}
        		
        		//vou pegar a sessão atual do contexto, e iniciar a transação
        		sf.getCurrentSession().beginTransaction();
        		 
                // Call the next filter (continue request processing)
                chain.doFilter(request, response);
      
                // Commit and cleanup
                if(sf.getCurrentSession().getTransaction().isActive())
                	sf.getCurrentSession().getTransaction().commit();
                 
        	} else {
        		
        		//para continuar o processo
        		chain.doFilter(request, response);
        		
        	}
 
        } catch (StaleObjectStateException staleEx) {
          
            // Rollback, close everything, possibly compensate for any permanent changes
            // during the conversation, and finally restart business conversation. Maybe
            // give the user of the application a chance to merge some of his work with
            // fresh data... what you do here depends on your applications design.
            throw staleEx;
            
        } catch (Throwable ex) {
        	
            // Rollback only
            ex.printStackTrace();

            try {
            	
            	if(sf != null){
            		
            		 if (sf.getCurrentSession().getTransaction().isActive()) {
                         sf.getCurrentSession().getTransaction().rollback();
                     }
            		
            	}
               
                
            } catch (Throwable rbEx) {
              
            }
 
            // Let others handle it... maybe another interceptor for exceptions?
            throw new ServletException(ex);
        }
        
    }
 
    public void init(FilterConfig filterConfig) throws ServletException {
    	
    	//não faço nada no init porque ainda não tenho nenhuma informação para criar a factory

    }
 
    public void destroy() {}
 
}

Obrigado. E qualquer dúvida retorno ao tópico.

Criado 24 de março de 2010
Ultima resposta 25 de mar. de 2010
Respostas 2
Participantes 2