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?
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
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
[code]
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() {}
}[/code]
Obrigado. E qualquer dúvida retorno ao tópico.