Parece algo ja muito falado na web. Mas o que vou tratar aqui nem todo mundo usa e as vezes sofre com certos tipos de erros.O caso descrito e o seguinte: Tenho um numero X de agencias bancarias do banco Y. E tenho que controlar as linhas telefonicas do banco.Cada cidade tem N agencias com N telefones cada. E cada agencia pode ter posto de auto atendimento em outros locais. Cada posto de auto atendimento tem uma agencia que e responsavel por ele. Preciso saber quais sao os terminais telefonicos de cada agencia.Trataremos da seguinte forma. O sistema sera implementado quando as agencias e suas linhas telefonicas ja estao em funcionamento. Entao teremos um banco de dados legado.Vou criar um DAO generico do tipo que tem muito tutorial por ai, depois vamos aperfeicoar.A vantagem do DAO generico e que ele pode ser utilizado para executar operacoes persistentes de qualquer entidade. primeiro, criamos a interface GenericDAOimport java.io.Serializable;import java.util.List;import org.hibernate.Session;public interface GenericDAO<T> { public Session getSession(); public T getById(Serializable id); public List<T> getAll(); public T save(T entity); public void delete(T entity);} Agora a classe que implementa a interface que acabamos de criarimport java.io.Serializable;import java.lang.reflect.ParameterizedType;import java.util.List;import org.hibernate.Session;import telefonia.dao.GenericDAO;public abstract class HibernateGenericDao<T> implements GenericDAO<T> { private Class<T> persistentClass; private Session session; @SuppressWarnings("unchecked") public HibernateGenericDao(Session session) { this.session = session; this.persistentClass = (Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()). getActualTypeArguments()[0]; } @Override public Session getSession() { return this.session; } @SuppressWarnings("unchecked") @Override public T getById(Serializable id) { return (T)this.session.get(this.persistentClass, id); } @SuppressWarnings("unchecked") @Override public List<T> getAll() { return this.session.createCriteria(this.persistentClass).list(); } @SuppressWarnings("unchecked") @Override public T save(T entity) { return (T)this.session.merge(entity); } @Override public void delete(T entity) { this.session.delete(entity); }}A classe terminal, que representa cada terminal ou linha telefonica.@Entity@Table (name="terminal") public class Terminal implements Serializable { private static final long serialVersionUID = 1L; private Long id; private Prefixo idPrefixo; private Operadora idOperadora; private Integer ddd; private Integer numero; private Date dataInstalacao; @Id @GeneratedValue @Column(name="id_terminal") public Long getId() { return id; } public void setId(Long id) { this.id = id; } //getters e settersAgora vamos criar o DAO para a entidade Terminal. Essa interface e uma especializacao de GenericDAO. Definimos que o tipo da entidade e Terminal, quando herdamos GenericDAO. public interface TerminalDao extends GenericDAO<Terminal> { public List<Terminal> getListaTerminaisPorNumeroDeTelefone(Long telefone); public Terminal getTerminalPorNumero(Long numero);}Vamos criar uma classe chamada HibernateTerminalDAO que herda as implementacoes do DAO generico para Hibernate (class HibernateGenericDAO) e implementa a interface TerminalDAO, que e uma interface que define metodos genericos e especificos. public class HibernateTerminalDao extends HibernateGenericDao<Terminal> implements TerminalDao { public HibernateTerminalDao(Session session) { super(session); } @Override public List<Terminal> getListaTerminaisPorNumeroDeTelefone(Long telefone) { return this.getSession().createCriteria(Terminal.class) .add(Restrictions.eq("numero", telefone.toString().substring(2, telefone.toString().length()))) .add(Restrictions.eq("ddd", Integer.parseInt(telefone.toString().substring(0, 2)))) .addOrder(Property.forName("numero").asc()) .list(); } @Override public Terminal getTerminalPorNumero(Long numero) { return (Terminal) this.getSession().createQuery("select t from Terminal t where t.numero = :tnum and t.ddd = :tddd"). setParameter("tnum", numero.toString().substring(2, numero.toString().length())). setParameter("tddd", Integer.parseInt(numero.toString().substring(0, 2))).uniqueResult(); }}A classe HibernateConnectionpublic class HibernateConnection { private static final SessionFactory sessionFactory; static { try { sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static Session getSession() { Session session = sessionFactory.openSession(); return session; }Agora finalmente vamos criar a tal da fabrica de conexoes (DAO)public abstract