2014-11-27 5 views
7

Ich habe viele Tabellen, für jede Tabelle haben wir DAO Interface und DAOImplementation Klasse.Transaction Management im Hibernate mit DAO Design Pattern

Beispiel DAO-Schnittstelle

public interface CancelPolicyDAO { 

public CancelPolicy insertCancelPolicy(CancelPolicy cpdao)throws ChannelDispatcherException; 

public CancelPolicy updateCancelPolicy(CancelPolicy cpdao)throws ChannelDispatcherException; 

public void deleteCancelPolicy(CancelPolicy cpdao)throws ChannelDispatcherException; 

public CancelPolicy findByCancelPolicyData(Integer id, Integer offSetUM, Integer nights, Float pOrAm, Byte isPercent)throws ChannelDispatcherException; 

public CancelPolicy findByCancelPolicyId(Integer id)throws ChannelDispatcherException; 
} 

Beispiel DAOImplementation Klasse

public class CancelPolicyDAOImpl implements CancelPolicyDAO { 

@Override 
public CancelPolicy insertCancelPolicy(CancelPolicy bean) throws ChannelDispatcherException { 

    Session ses = null; 
    try { 

     ses = HibernateConnector.getInstance().getSession(); 
     ses.save(bean); 
     ses.flush(); 
     return bean; 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new ChannelDispatcherException(DbUtil.getStackTraceMessage(e)); 
    } finally { 
     if (ses != null) { 
      try { 
       ses.close(); 
      } catch (Exception er) { 
       er.printStackTrace(); 
      } 
     } 
    } 

} 

@Override 
public CancelPolicy updateCancelPolicy(CancelPolicy bean) throws ChannelDispatcherException { 
    Session sess = null; 

    try { 

     sess = HibernateConnector.getInstance().getSession(); 
     sess.update(bean); 
     sess.flush(); 
     return bean; 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new ChannelDispatcherException(DbUtil.getStackTraceMessage(e)); 
    } 

} 

@Override 
public void deleteCancelPolicy(CancelPolicy bean) throws ChannelDispatcherException { 
    Session sess = null; 

    try { 

     sess = HibernateConnector.getInstance().getSession(); 
     sess.delete(bean); 
     sess.flush(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
     throw new ChannelDispatcherException(DbUtil.getStackTraceMessage(e)); 
    } 

} 

@Override 
public CancelPolicy findByCancelPolicyData(Integer id, Integer offSetUM, Integer nights, Float pOrAm, Byte isPercent) throws ChannelDispatcherException { 

    Session ses = null; 
    try { 
     ses = HibernateConnector.getInstance().getSession(); 
     Query query = ses.createQuery("from CancelPolicy a where " 
       + " a.cancelPolicyTypeId =:cancelPolicyTypeId " 
       + " and a.offsetUnitMultiplier =:offsetUnitMultiplier " 
       + " and a.nights =:nights " 
       + " and a.percentOramount =:percentOramount " 
       + " and a.isPercent =:isPercent"); 

     query.setParameter("cancelPolicyTypeId", id); 
     query.setParameter("offsetUnitMultiplier", (offSetUM)); 
     query.setParameter("nights", (nights)); 
     query.setParameter("percentOramount", pOrAm); 
     query.setParameter("isPercent", isPercent); 

     List queryList = query.list(); 
     if (queryList != null && queryList.isEmpty()) { 
      return null; 
     } else { 
      return (CancelPolicy) queryList.get(0); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new ChannelDispatcherException(DbUtil.getStackTraceMessage(e)); 
    } finally { 
     if (ses != null) { 
      try { 
       ses.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

public CancelPolicy findByCancelPolicyId(Integer id) throws ChannelDispatcherException { 

    Session ses = null; 
    try { 
     ses = HibernateConnector.getInstance().getSession(); 
     Query query = ses.createQuery("from CancelPolicy a where " 
       + " a.id =:id "); 

     query.setParameter("id", id); 

     List queryList = query.list(); 
     if (queryList != null && queryList.isEmpty()) { 
      return null; 
     } else { 
      return (CancelPolicy) queryList.get(0); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     throw new ChannelDispatcherException(DbUtil.getStackTraceMessage(e)); 
    } finally { 
     if (ses != null) { 
      try { 
       ses.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

Beispiel main-Methode

public static void main(String[] args) { 

     // How to handel Transaction in Hibernate ? 
    CancelPolicyDAO cancelPolicyDAO = HibernateDAOFactory.getInstance().getCancelPolicyDAO(); 


    CancelPolicy insertCancelPolicy = cancelPolicyDAO.findByCancelPolicyData(2, 76, 25, 25.36f, 3); 
    if(insertCancelPolicy==null){ 
     CancelPolicy cancelPolicy = new CancelPolicy(); 
    cancelPolicy.setCancelPolicyTypeId(1); 
    cancelPolicy.setNights(2); 
    insertCancelPolicy = cancelPolicyDAO.insertCancelPolicy(cancelPolicy); 
    } 
    Integer autoIncrementId = insertCancelPolicy.getId(); 

    AvailabilityDAO availabilityDAO = HibernateDAOFactory.getInstance().getAvailabilityDAO(); 
    Availability availability = new Availability(); 
//  using CancelPolicy autoIncrementId 
    availability.setId(autoIncrementId); 
    availability.setCount(2); 
    availability.setMaxLos(5); 
    availabilityDAO.insertAvailability(availability); 
    . 
    . 
    . 
    . 
    . 


} 

Nun ist meine Frage wie kann ich Transaktion in DAOImpl den Griff? Sollte ich Session Object als Parameter für jeden DAOImpl übergeben oder gibt es einen besseren Ansatz?

+1

Verwenden Sie AOP-basierte TX-Verwaltung und löschen Sie 80% Ihres Codes. –

+0

Verwenden Sie das Spring-Framework? Wenn ja, schau dir das mal an: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html – Anarki

+0

@Anarki no im nur mit Jse (core java) – LMK

Antwort

10

Ich würde dringend empfehlen, das Rad nicht neu zu erfinden; Verwenden Sie vorhandenen, robusten und getesteten Code.

Die Kommentare erwähnt bereits AOP und die Spring Rahmen. Dies ist der Weg zu gehen. Das Spring-Framework hat sogar ein Unterprojekt namens Spring Data, mit dem Sie Ihre Finder-Methoden (wie findByCancelPolicyData) deklarativ definieren können.

Dies wird Ihnen eine Menge Arbeit ersparen.

Wenn Sie aus irgendeinem Grund Spring nicht verwenden möchten/können, können Sie die erstaunlich gute Dokumentation des Basisframeworks und der genannten Spring Data immer noch lesen, um viele gute Ideen bezüglich der Transaktion (über AOP), Code-Wiederverwendung (über generische DAOs) oder API-Design. Verpassen Sie nicht diese Lektüre.

1

Keine Notwendigkeit Frameworks zu verwenden, ist das CancelPolicy Objekt das Hauptobjekt und es sollte hat Eigenschaft (Kaskade) überprüfen Sie den Link (Cascading life cycle) winter

Sie das CancelPolicy Objekt mit allen erforderlichen Beziehungen So füllen und sagen speichern , wird der gesamte Graph der zugehörigen Objekte gespeichert.

7

Während die Verwendung von Spring wahrscheinlich der beste Weg ist, um die Transaktionsverwaltung hinzuzufügen, können Sie es immer noch ausarbeiten, ohne Ihre gesamte Code-Basis neu zu faktorisieren.

Was Sie tun müssen, ist die folgende Konfiguration einstellen:

Sie DAOs sollte die Session Zugriff durch:

[SessionFactory.getCurrentSession()][1]; 

Sie müssen noch Transaktionsgrenzen in der Service-Ebene erklären:

Session sess = factory.openSession(); 
Transaction tx = null; 
try { 
    tx = sess.beginTransaction(); 

    dao1.find(); 
    dao2.save(entity); 

    tx.commit(); 
} 
catch (RuntimeException e) { 
    if (tx != null) tx.rollback(); 
    throw e; 
} 
finally { 
    sess.close(); 
} 

Sowohl dao1 als auch dao2 verwenden denselben Hibernate Se und die gleiche Transaktion.

Um diese ausführliche Transaktionsmanagement Code zu vermeiden Umgang mit Ihnen eine einfache Transaction Dienstprogramm wie schreiben:

pubic static abstract class TransactionCallable<T> { 
    public abstract T execute(); 
} 

public class TransactionManager { 
    pubic static <T> T doInTransaction(TransactionCallable<T> callable) { 
     T result = null; 
     Session session = null; 
     Transaction txn = null; 
     try { 
      session = sf.openSession(); 
      txn = session.beginTransaction(); 

      result = callable.execute(); 
      txn.commit(); 
     } catch (RuntimeException e) { 
      if (txn != null && txn.isActive()) txn.rollback(); 
      throw e; 
     } finally { 
      if (session != null) { 
       session.close(); 
      } 
     } 
     return result; 
    } 
} 

Und das ist, wie ein Dienst wird wie folgt aussehen:

TransactionManager.doInTransaction(new TransactionCallable<Void>() { 
    @Override 
    public Void execute() { 
     dao1.find(); 
     dao2.save(entity); 
    } 
}); 
+0

Ziemlich nett. Ich war auf der Suche nach so etwas. Während jeder immer wieder sagt, dass Spring der einzig mögliche Weg ist, funktionieren existierende Code-Implementierungen mit dem zusätzlichen Vorteil, dass nicht alle zusätzlichen Abhängigkeiten hinzugefügt werden müssen. – ibelcomputing

2

Wenn Sie haben Web-Anwendung, und Sie verwenden nicht Frühling in Ihrem Projekt für Session Mgmt, würde ich vorschlagen, Interceptor zu verwenden, um die Session-Handling-Logik außerhalb Ihres DAO zu trennen. Sie können unten erwähnten Artikel für das gleiche beziehen. Beachten Sie, dass mit diesem Ansatz bestimmte CONs verbunden sind, aber wir haben festgestellt, dass dies in unserem Fall der bequemste Weg ist.

Open Session in View Pattern

Unten ist das Beispiel dafür, wie wir Open Session in View-Muster mit Generics verwenden, können wir für die Klasse haben,

public class CancelPolicyDAOImpl extends GenericDAOImpl<CancelPolicy, Long> implements CancelPolicyDAO { 

    @Override 
public CancelPolicy insertCancelPolicy(CancelPolicy bean) throws ChannelDispatcherException { 


     try { 
      // save method is implemented in GenericDAOImpl described below. 
      return save(bean); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     } 
//remaining methods 
} 

In obigen Codespeichermethode verwendet wird, die implementiert ist in GenericHibernateDAOImpl wie unten gezeigt. Sie können Google für GenericHibernateDAOImpl Klasse und greifen Sie es, die Anzahl der zusätzlichen Methoden für grundlegende Operationen hat.

public abstract class GenericDAOImpl<T, ID extends Serializable> { 

    private Session session; 

public T save(final T entity) { 
     Transaction trans = null; 
     try { 
      trans = session.beginTransaction(); 
      session.saveOrUpdate(entity); 
      session.flush(); 
      trans.commit(); 
     } catch (Exception ex) { 
      rollBackTransaction(trans); 
// you might require to throw error again here 
     } 
     return entity; 
    } 

//in case any complex operations required you can get core session object from this method 
    protected Session getSession() { 
     return sessionFactory.getCurrentSession(); 
    } 
} 

Nun zurück zu Ihrer Frage, wo die Sitzung zu erhalten, wie oben GenericHibernateDAOImpl Sitzung gezeigt wird von Singleton session durch getCurrentSession Methode abgerufen. Beachten Sie, dass Sie eine aktive Transaktion ausführen müssen, bevor Sie die aktuelle Sitzung abrufen, die Sie in Ihrem Interceptor bereitstellen können (Link am Anfang dieses Posts).

Bitte lassen Sie es mich wissen.