class DAOFactory { public static DAOFactory getDAOFactory() { return new HibernateDAOFactory(); } public abstract void startTransaction(); public abstract void cancelTransaction(); public abstract void finalize(); public abstract TerminalDao getTerminalDao();}A classe HibernateDAOFactory que implementa os metodos da classe abstrata DAOFactorypublic class HibernateDAOFactory extends DAOFactory { private Session session; private Transaction tx; public HibernateDAOFactory() { this.session = HibernateConnection.getSession(); } @Override public void cancelTransaction() { this.tx.rollback(); this.tx = null; } @Override public void startTransaction() { this.tx = this.session.beginTransaction(); } @Override public void finalize() { if (this.tx != null) { this.tx.commit(); } this.session.close(); } @Override public TerminalDao getTerminalDao() { return new HibernateTerminalDao(this.session); }}Agora para instanciar o DAO, vamos criar os seguintes metodos:public Terminal getTerminalPorNumero(Long numero) throws DaoException { DAOFactory daoFactory = DAOFactory.getDAOFactory(); TerminalDao terminalDao = daoFactory.getTerminalDao(); daoFactory.startTransaction(); Terminal t = terminalDao.getTerminalPorNumero(numero); daoFactory.finalize(); return t; } public List<Terminal> getListaTerminaisPorNumeroDeTelefone(Long telefone) { DAOFactory daoFactory = DAOFactory.getDAOFactory(); TerminalDao terminalDao = daoFactory.getTerminalDao(); daoFactory.startTransaction(); List<Terminal> terminais = terminalDao.getListaTerminaisPorNumeroDeTelefone(telefone); daoFactory.finalize(); return terminais; } Ambos os metodos acima irao consultar na base de dados o terminal ou uma lista de terminais (caso haja repeticao de um mesmo numero com ddd igual para agencias diferentes). Observe que nossa base de dados e legada, entao esse e um erro que provocarei para explicar melhor essa fabrica de conexao.Agora finalmente, vamos criar um metodo que vai verificar se existe numeros repetidos (mesmo ddd e numero de telefone) na base de dados. private static Terminal verificaNumeroRepetido(String ddd, String numero) { Long num = new Long(ddd.concat(numero)); Terminal terminal = null; try { terminal = new TerminalService().getTerminalPorNumero(num); } catch (NonUniqueResultException nre) { List<Terminal> listaTerminais = new TerminalService().getListaTerminaisPorNumeroDeTelefone(new Long(ddd.concat(numero))); //aqui tenho uma relacao dos numeros repetidos. Ai o que eu decido o que faco com eles... } return terminal; }O metodo acima consulta um terminal da base pelo ddd + numero. Ate ai tudo bem. Caso haja repeticao de ddd e numero, pego a lista de numeros repetidos e decido qualquer coisa a ser feito com eles. O problema, e que quando pegar um numero repetido vai gerar uma excessao do tipo NonUniqueResultException e nao vai fechar a conexao, vai manter a conexao aberta.Suponhamos que no pool de conexoes do hibernate foi definido no maximo 10 conexoes simultaneas:<!-- Pool de conexoes --><property name="hibernate.c3p0.min_size">2</property><property name="hibernate.c3p0.max_size">10</property>Isso implica que quando 10 usuarios utilizarem essa rotina, ou mesmo um usuario repetir esse processo 10 vezes, a consulta vai literalmente parar esperando uma das conexoes cair para tentar instanciar uma nova conexao, ou seja, o sistema vai parar!O correto seria fazer o sistema prevenir esse tipo de excessao e nao instanciar conexoes novas enquanto existirem abertas.Melhorando a fabrica de conexoesVamos modificar a classe HibernateConnection. E la que instanciamos novas conexoespublic class HibernateConnection { private static final SessionFactory sessionFactory; private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>(); static { try { sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static Session getSession() { if ((threadSession.get() == null) || (!threadSession.get().isOpen())) { Session session = sessionFactory.openSession(); threadSession.set(session); return session; } else { Session session = threadSession.get(); return session; } } public static void closeSession() { Session session = threadSession.get(); threadSession.set(null); try