Dúvida na delegação de controle entre as camadas MVC

Pessoal, é o seguinte, precisamos de opiniões sobre a seguinte situação.

Estamos desenvolvendo um pequeno sistema e usando na camada de persistência o hibernate. A nossa dúvida é referente a delegar controle sobre a transação e a sessão no hibernate.

Existem duas situações, e precisamos saber qual usar.

A primeira hipótese (implementada como teste nas listagens abaixo) é que deve-se criar a sessão e a transação fora dos DAOs, passar a sessao para os DAOs e no final na utilização dos mesmos dar um commit na transação e fechar a sessão.

A outra hipótese é deixar que o controle da sessão e da transação fique totalmente por responsabilidade do DAO.

Eu defendo a primeira hipótese, pois assim podemos ter maior controle.
O que vocês acham?
Dêem uma olhada nas listagens.

[code]
package usandohibernate.entity;

import javax.persistence.*;

/**
*

  • @author David Buzatto
    */
    @Entity
    public class Cliente {

    @Id
    @GeneratedValue
    private Long id;

    @Column(
    length = 30,
    nullable = false
    )
    private String nome;

    @Column(
    length = 50,
    nullable = false
    )
    private String sobrenome;

    public Long getId() {
    return id;
    }

    public void setId(Long id) {
    this.id = id;
    }

    public String getNome() {
    return nome;
    }

    public void setNome(String nome) {
    this.nome = nome;
    }

    public String getSobrenome() {
    return sobrenome;
    }

    public void setSobrenome(String sobrenome) {
    this.sobrenome = sobrenome;
    }

}[/code]

[code]
package usandohibernate.entity;

import javax.persistence.*;

/**
*

  • @author David Buzatto
    */
    @Entity
    public class Produto {

    @Id
    @GeneratedValue
    private Long id;

    @Column(
    length = 30,
    nullable = false
    )
    private String nome;

    @Column(
    length = 50,
    nullable = false
    )
    private String descricao;

    private Double preco;

    public Long getId() {
    return id;
    }

    public void setId(Long id) {
    this.id = id;
    }

    public String getNome() {
    return nome;
    }

    public void setNome(String nome) {
    this.nome = nome;
    }

    public String getDescricao() {
    return descricao;
    }

    public void setDescricao(String descricao) {
    this.descricao = descricao;
    }

    public Double getPreco() {
    return preco;
    }

    public void setPreco(Double preco) {
    this.preco = preco;
    }

}[/code]

[code]
package usandohibernate.entity;

/**

  • Enumeração das entidades.

  • @author David Buzatto
    */
    public enum EntityEnum {

    // entidades

    /**

    • Cliente.
      */
      CLIENTE( Cliente.class ),

    /**

    • Produto.
      */
      PRODUTO( Produto.class );

    private Class entity;

    EntityEnum( Class entity ) {
    setEntity( entity );
    }

    private void setEntity( Class entity ) {
    this.entity = entity;
    }

    public Class getEntity() {
    return entity;
    }

}[/code]

[code]
package usandohibernate.hibernate;

import org.hibernate.;
import org.hibernate.cfg.
;
import usandohibernate.entity.*;

/**

  • Fábrica de sessões do hibernate.

  • Utiliza uma enumeração de classes anotadas para popular a configuração.

  • @author David Buzatto
    */
    public class HibernateFactory {

    // fábrica de sessões
    private static final SessionFactory factory;

    /*

    • AnnotationConfiguration, responsável em armazenar as configurações
    • das classes anotadas.
      */
      private static final AnnotationConfiguration config;

    /*

    • Permite que as sessions associadas sejam locais a thread que a está executando.
      */
      private static final ThreadLocal< Session > threadLocal =
      new ThreadLocal< Session >();

    // bloco de inicialização estático (executado apenas UMA vez)
    static {

     // cria a AnnotationConfiguration, evitando uso do arquivo hibernate.cfg.xml
     config = new AnnotationConfiguration();
     
     // adiciona as classes anotadas
     EntityEnum[] entities = EntityEnum.values();
     
     for ( int i = 0; i < entities.length; i++ ) {
         config.addAnnotatedClass( entities[ i ].getEntity() );
     }
     
     // cria a factory
     factory = config.buildSessionFactory();
    

    }

    public SessionFactory getFactory() {

     return factory;
    

    }

    public AnnotationConfiguration getConfig() {

     return config;
    

    }

    public Session getSession() {

     Session session = factory.openSession();
     threadLocal.set( session );
     return factory.openSession();
    

    }

}[/code]

[code]
package usandohibernate.dao;

import java.util.;
import org.hibernate.
;
import usandohibernate.entity.*;

/**
*

  • @author David Buzatto
    */
    public class ClienteDAO< T extends Cliente > {

    private Session session;
    private Class classe = Cliente.class;

    public ClienteDAO( Session session ) {

     this.session = session;
    

    }

    public void adiciona( T obj ) throws HibernateException {

     this.session.save( obj );
    

    }

    public void remove( T obj ) throws HibernateException {

     this.session.delete( obj );
    

    }

    public void atualiza( T obj ) throws HibernateException {

     this.session.update( obj );
    

    }

    public T procuraPorId( Long id ) throws HibernateException {

     return ( T ) this.session.load( classe, id );
    

    }

    public List< T > procuraPorNome( String nome ) throws HibernateException {

     Query query = this.session.createQuery(
             
             "FROM usandohibernate.entity.Cliente " +
             "WHERE nome LIKE ? "
             
     );
     
     query.setString( 0, nome );
     
     return query.list();
    

    }

    public List< T > procuraPorSobrenome( String sobrenome ) throws HibernateException {

     Query query = this.session.createQuery(
             
             "FROM usandohibernate.entity.Cliente " +
             "WHERE sobrenome LIKE ? "
             
     );
     
     query.setString( 0, sobrenome );
     
     return query.list();
    

    }

    public List< T > listaTudo() throws HibernateException {

     return this.session.createCriteria( classe ).list();
    

    }

    public List< T > listaPagina( int inicio, int quantia )
    throws HibernateException {

     return this.session.createCriteria( classe ).
            setMaxResults( quantia ).setFirstResult( inicio ).list();
    

    }

}[/code]

[code]
package usandohibernate.dao;

import java.util.;
import org.hibernate.
;
import usandohibernate.entity.*;

/**
*

  • @author David Buzatto
    */
    public class ProdutoDAO< T extends Produto > {

    private Session session;
    private Class classe = Produto.class;

    public ProdutoDAO( Session session ) {

     this.session = session;
    

    }

    public void adiciona( T obj ) throws HibernateException {

     this.session.save( obj );
    

    }

    public void remove( T obj ) throws HibernateException {

     this.session.delete( obj );
    

    }

    public void atualiza( T obj ) throws HibernateException {

     this.session.update( obj );
    

    }

    public T procuraPorId( Long id ) throws HibernateException {

     return ( T ) this.session.load( classe, id );
    

    }

    public List< T > procuraPorNome( String nome ) throws HibernateException {

     Query query = this.session.createQuery(
             
             "FROM usandohibernate.entity.Produto " +
             "WHERE nome LIKE ? "
             
     );
     
     query.setString( 0, nome );
     
     return query.list();
    

    }

    public List< T > procuraPorDescricao( String descricao ) throws HibernateException {

     Query query = this.session.createQuery(
             
             "FROM usandohibernate.entity.Produto " +
             "WHERE descricao LIKE ? "
             
     );
     
     query.setString( 0, descricao );
     
     return query.list();
    

    }

    public List< T > procuraPorPreco( Double preco ) throws HibernateException {

     Query query = this.session.createQuery(
             
             "FROM usandohibernate.entity.Produto " +
             "WHERE preco = ? "
             
     );
     
     query.setDouble( 0, preco );
     
     return query.list();
    

    }

    public List< T > listaTudo() throws HibernateException {

     return this.session.createCriteria( classe ).list();
    

    }

    public List< T > listaPagina( int inicio, int quantia )
    throws HibernateException {

     return this.session.createCriteria( classe ).
            setMaxResults( quantia ).setFirstResult( inicio ).list();
    

    }

}[/code]

[code]
package usandohibernate;

import org.hibernate.;
import usandohibernate.dao.
;
import usandohibernate.entity.;
import usandohibernate.hibernate.
;

/**
*

  • @author David Buzatto
    */
    public class Testes {

    public static void main( String[] args ) {

     Produto p = new Produto();
     p.setNome( "arroz" );
     p.setDescricao( "comida..." );
     p.setPreco( 3.5 );
     
     Cliente c = new Cliente();
     c.setNome( "david" );
     c.setSobrenome( "buzatto" );
     
     Session session = null;
     Transaction t = null;
     
     try {
         
         session = new HibernateFactory().getSession();
         t = session.beginTransaction();
         
         new ProdutoDAO( session ).adiciona( p );
         new ClienteDAO( session ).adiciona( c );
         
         t.commit();
         
     } catch ( HibernateException exc ) {
         
         // tratar excessões específicas aqui
         
         if ( t != null )
             t.rollback();
         
     } finally {
         
         if ( session != null )
             session.close();
         
     }
    

    }

}[/code]

Aguardo resposta!

eu acho q vc deve no construtor da dao instanciar o session e dar um close nele em cada chamada de metodo