Visualizzazione dei risultati da 1 a 9 su 9

Discussione: DAO e transazioni

  1. #1

    DAO e transazioni

    Ciao,
    nella mia applicazione devo interagire con un database
    utilizzo dao

    - ottengo DAO factory
    - domando al DAO factory di creare un nuovo DAO
    - uso il DAO

    In ogni metodo del DAO chiamo il metodo statico di DAOFactory createConnection per ottenere la connessione, utilizzando c3p0 per la gestione del connection pool

    Ma se io volessi fare due query che devono terminare entrambe per essere una transazione valida cosa devo fare?

    Senza DAO sarebbe(vado a memoria):
    con = new Connection(..)
    con.setAutocommit(false)
    Statement st = con.createStatement();
    st.execute(query1);
    st.execute(query2)
    con.commit();

    cioè utilizzando commit, roolback.
    Come si può fare?

  2. #2
    ottengo DAO factory
    - domando al DAO factory di creare un nuovo DAO
    - uso il DAO
    E noi come facciamo a sapere cosa intendi tu per DAO, DAO FACTORY etc...

  3. #3
    Originariamente inviato da francesco.muia
    E noi come facciamo a sapere cosa intendi tu per DAO, DAO FACTORY etc...
    Hai ragione scusa:

    Allora io ho fatto:

    codice:
    public abstract class DAOFactory
    {		
    	public abstract Classe1DAO getClasse1DAO();
            public abstract Classe2DAO getClasse2DAO();
    
    	public static DAOFactory getDAOFactory() 
    	{
              return new PostgresDAOFactory(hDb, usDb,pDb);		
    	}
    }
    
    public class PostgresDAOFactory extends DAOFactory
    {
       public PostgresDAOFactory(String hDb,String uDb,String pDb)
       {
          dataSoruce = getDatasource(); //ottiene datasource 
       }
       public static Connection getConnection() throws SQLException
       {
    	return dataSource.getConnection();
       }
    
      @Override
      public Classe1DAO getClasse1DAO()
      {
    	return new Classe1DAOImpl();
      }
    
      @Override
      public Classe2DAO getClasse2DAO()
      {
    	return new Classe2DAOImpl();
      }
    }
    
    public interface Classe1DAO 
    {
       void prova1();
    }
    public interface Classe2DAO 
    {
       void prova1();
    }
    
    e infine le classe che implentano le interfacce
    
    public Classe1DAOImpl extends Classe1DAO()
    {
       public prova1() 
      {
         query = //da file
         try (Connection con = PostgresDAOFactory.getConnection();
    	   PreparedStatement stmt = con.prepareStatement(query))
    	{
    				
    		try (ResultSet rs = stmt.executeQuery())
    		{
    					//..
    		}
    	}
      }
    }

  4. #4
    Continua a mancare qualcosa ma più o meno o capito che vorresti implementare il pattern DAO.
    Cmq non vedo dove sia il problema, una volta ottenuto il tuo DAO tramite factory o altro.
    Avrai il tuo oggetto DAO coi i suoi metodo per esempio eseguiOperazione che chiederà al dao la connessione e farà quello che ci vuole compreso commit e rollback e via dicendo.

  5. #5
    Originariamente inviato da francesco.muia
    Continua a mancare qualcosa ma più o meno o capito che vorresti implementare il pattern DAO.
    Cmq non vedo dove sia il problema, una volta ottenuto il tuo DAO tramite factory o altro.
    Avrai il tuo oggetto DAO coi i suoi metodo per esempio eseguiOperazione che chiederà al dao la connessione e farà quello che ci vuole compreso commit e rollback e via dicendo.
    Il mio problema è questo:

    DAOFactory daoFactory = DAOFactory.getDAOFactory();
    Classe1DAO c1DAO = daoFactory.getClasse1DAO();
    Classe2DAO c2DAO = daoFactory.getClasse2DAO();

    c1DAO.prova1();
    c2DAO.prova1();

    Se c2DAO.prova1() fallisce deve fare il rollback anche di c1DAO.
    Ma se la connessione viene gestita dentro c1DAO come faccio a fargli fare il rollback?

  6. #6
    Faccio un esempio di come progetterei la cosa io (non è detto che sia la migliore )
    codice:
    public abstract class DAOFactory {
        public abstract Classe1DAO getClasse1DAO();
    
        public abstract Classe2DAO getClasse2DAO();
    
        public abstract Classe1DAO getClasse1DAO(Connection connection);
    
        public abstract Classe2DAO getClasse2DAO(Connection connection);
    
        public static DAOFactory getDAOFactory() {
            return new PostgresDAOFactory(hDb, usDb, pDb);
        }
    
    }
    public class PostgresDAOFactory extends DAOFactory {
    
        public PostgresDAOFactory(String hDb, String uDb, String pDb) {
            dataSoruce = getDatasource(); // ottiene datasource
        }
    
        public static Connection getConnection() throws SQLException {
            return dataSource.getConnection();
        }
    
        @Override
        public Classe1DAO getClasse1DAO() {
            return this.getClasse1DAO(PostgresDAOFactory.getConnection());
        }
    
        @Override
        public Classe2DAO getClasse2DAO() {
            return this.getClasse2DAO(PostgresDAOFactory.getConnection());
        }
    
        @Override
        public Classe1DAO getClasse1DAO(Connection connection) {
            return new Classe1DAOImpl(connection);
        }
    
        @Override
        public Classe2DAO getClasse2DAO(Connection connection) {
            return new Classe2DAOImpl(connection);
        }
    }
    public interface Classe1DAO {
        void prova1();
    
        public boolean operazioneAtomica();
    
        public void soloOperazioneAtomica();
    }
    public class Classe1DAOImpl implements Classe1DAO {
    
        private Connection connection;
    
        public Classe1DAOImpl(Connection connection) {
            this.connection = connection;
        }
    
        @Override
        public void prova1() {
            if (operazioneAtomica()) {
                Classe2DAO classe2dao = DAOFactory.getDAOFactory().getClasse2DAO(connection);// SHARE CONNECTION WITH DAO 2
                if (classe2dao.operazioneAtomica()) {
                    // commit
                } else {
                    // rollback;
                }
            }
        }
    
        @Override
        public boolean operazioneAtomica() {
            // FACCIO LA MIO OPERAZIONE ATOMICA (SENZA COMMIT O ROLLBACK)
            return true;
        }
    
        public void soloOperazioneAtomica() {
            if (this.operazioneAtomica()) {
                // commit
            } else {
                // rollback
            }
        }
    }
    public interface Classe2DAO {
        void prova1();
    
        public boolean operazioneAtomica();
    }
    public class Classe2DAOImpl implements Classe2DAO {
    
        public Classe2DAOImpl(Connection connection) {
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void prova1() {
            if (this.operazioneAtomica()) {
                // commit
            } else {
                // rollback
            }
    
        }
    
        @Override
        public boolean operazioneAtomica() {
            // FACCIO LA MIO OPERAZIONE ATOMICA (SENZA COMMIT O ROLLBACK)
            return false;
        }
    }
    Allora le principale modiche che ho fatto è stata quella di introdurre un costruttore nelle Classi DAO che accetti un oggetto Connection (plausibile dato che dovranno effettuare operazione sul database), ho modificato anche la factory in modo da poter creare i dao sia senza passare l'oggetto connection, caso in cui voglio che i DAO lavorino su connessioni diverse.
    Nei DAO o suddiviso le operazioni atomiche in modo da poterle richiamare a cascata (metodo prova1 di Classe1DAOImpl) oppure singolarmente (metodo soloOperazioneAtomica di Classe1DAOImpl).

    Ovviamente questa progettazione si basa da quello che mi hai detto fin'ora e quindi non garantisco che sia la miglior progettazione per il resto del programma.


  7. #7
    ti ringrazio per il tempo che stai usando per me però facendo come dici te dovrei richiamare Classe2Dao in classe1Daoimpl. Non dovrebbe essere indipendente i? Anche perché finche sono due transazioni da fare va bene ma se diventano 4/5 non si complica troppo?

    Quello che devo fare è usarle in una servlet
    quindi avro

    doPost(...)
    {
    classe1Dao.prova1();
    classe2Dao.prova2();
    classe3Dao.prova3();
    //etc.
    }

    Però mi hai dato lo spunto per quest'idea.
    sarebbe corretto ottener la connessione nella servlet e passarla come parametro. Cioè:

    doPost(...)
    {
    Connection con = DaoFactory.getConnection();
    con.setAutoCommit(false);
    classe1Dao.prova1(con);
    classe2Dao.prova2(con);
    classe3Dao.prova3(con);
    con.commit();
    //
    }

    e magari implemntare i metodi prova1 sia con il parametro connection che senza?

  8. #8
    però facendo come dici te dovrei richiamare Classe2Dao in classe1Daoimpl. Non dovrebbe essere indipendente i?
    Tutti i DAO sono indipendenti, ma questo non vuol dire che non possono collaborare insieme.
    Se per esempio, hai due tabelle che sono in relazione 1-N (babbo figlio per intenderci) e quindi giustamente avrai il DAO per gestire la classe BABBO e il DAO della classe FIGLIO.
    Ora supponiamo di dover salvare un babbo con i figli, tu sicuramente vorresti fare BABBO_DAO.salva e poi FIGLIO_DAO.salva, mentre per me è molto più corretto che sia il BABBO_DAO ad occuparsi di salvare anche i figli e questo lo può fare o inserendo il codice di salvataggio dei nel proprio metodo di salvataggio oppure "Delegando" la cosa al DAO che gestisce i figli (e direi che la seconda è migliore).
    Però mi hai dato lo spunto per quest'idea.
    sarebbe corretto ottener la connessione nella servlet e passarla come parametro. Cioè:

    doPost(...)
    {
    Connection con = DaoFactory.getConnection();
    con.setAutoCommit(false);
    classe1Dao.prova1(con);
    classe2Dao.prova2(con);
    classe3Dao.prova3(con);
    con.commit();
    //
    }
    Facendo cosi però deleghi la gestione del database alla servlet (commit e rollback), e suppongo che oltre al DAO tu voglia seguire anche MVC e quindi la cosa non va bene sia per quanto riguarda MVC ma secondo anche per il DAO in quanto dovrebbe essere quest'ultimo a prendersi carico della gestione del database.
    Cosi facendo, non separando le responsabilità, cosa succederebbe se, in corso d'opera, ti dicessero di non usare un database ma bensi un file txt.
    Con il tuo approccio dovresti cambiare tutto lo strato di view.
    Nel mio caso l'unica cosa da cambiare sarebbe la Factory e l'introduzione di nuovi DAO per la gestione del salvataggio sul file.

  9. #9
    Originariamente inviato da francesco.muia
    Tutti i DAO sono indipendenti, ma questo non vuol dire che non possono collaborare insieme.
    Se per esempio, hai due tabelle che sono in relazione 1-N (babbo figlio per intenderci) e quindi giustamente avrai il DAO per gestire la classe BABBO e il DAO della classe FIGLIO.
    Ora supponiamo di dover salvare un babbo con i figli, tu sicuramente vorresti fare BABBO_DAO.salva e poi FIGLIO_DAO.salva, mentre per me è molto più corretto che sia il BABBO_DAO ad occuparsi di salvare anche i figli e questo lo può fare o inserendo il codice di salvataggio dei nel proprio metodo di salvataggio oppure "Delegando" la cosa al DAO che gestisce i figli (e direi che la seconda è migliore).

    Facendo cosi però deleghi la gestione del database alla servlet (commit e rollback), e suppongo che oltre al DAO tu voglia seguire anche MVC e quindi la cosa non va bene sia per quanto riguarda MVC ma secondo anche per il DAO in quanto dovrebbe essere quest'ultimo a prendersi carico della gestione del database.
    Cosi facendo, non separando le responsabilità, cosa succederebbe se, in corso d'opera, ti dicessero di non usare un database ma bensi un file txt.
    Con il tuo approccio dovresti cambiare tutto lo strato di view.
    Nel mio caso l'unica cosa da cambiare sarebbe la Factory e l'introduzione di nuovi DAO per la gestione del salvataggio sul file.
    Ho capito (forse )
    Sei stato gentilissimo. grazie mille!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.