Come riutilizzare il codice boilerplate per la gestione delle sessioni di Hibernate?

1

La mia applicazione Java utilizza Hibernate come framework ORM. Mi trovo spesso a scrivere codice come questo:

Session session = HibernateUtil.getSessionFactory().openSession();
try {
    session.beginTransaction();

    // do some work, which might or might not yield a result which will be returned
    doWork(session);
    // it also might involve using and changing local variables, like success and failure counters

    session.getTransaction().commit();
    return result;
} catch (Exception e) {

    // optional: log the exception
    Utility.logException("some log node", e);
    // Also, some other actions like sending an alert email might happen at this place.

    if (session.getTransaction().isActive()) {
        session.getTransaction().rollback();
    }

    // optional: rethrow the exception
    //throw e;
} finally {
    if (session.isOpen()) {
        session.close();
    }
}

e mi chiedo se c'è un buon modo per inserire questo codice "boilerplate" in un unico metodo. Il doWork spesso (ma non sempre) comporta la modifica delle variabili locali.

Se si trattava di un'applicazione C #, avrei creato un metodo come questo:

public static void DoWorkInSession(Action<Session> workToDo, String logNode, bool rethrowException)

e chiama l'azione workToDo all'interno del metodo.

L'uso della reflection (che già faccio in alcuni punti) risolve solo parzialmente il problema e rende meno convenienti gli errori di logging con 'InvocationTargetException's. Ci sono altri (migliori) modi per farlo, ad es. usando le funzionalità di Java 8 che sto lentamente iniziando a scoprire?

    
posta Glorfindel 22.04.2017 - 21:17
fonte

1 risposta

2

Utilizza l'ereditarietà.

Questo codice segue già il modello Metodo modello , con doWork() come metodo chiamato dal modello. Trasforma questo codice in una superclasse astratta e sottoclassi tutti i metodi di accesso a Hibernate da esso.

O meglio, usa un modello fornito da una libreria di terze parti e che evita problemi come session.close() che genera un'eccezione di mascheramento. Una possibilità è HibernateTemplate di Spring, e tu potrebbe trovare utile anche la gestione dichiarativa delle transazioni di Spring.

Oppure, se sei contrario a Spring, ci sono altre alternative. Attualmente sto lavorando a un progetto che usa Guice con MyBatis, che non mi piace particolarmente, ma YMMV.

Se vuoi davvero utilizzare le funzionalità Java8, piuttosto che un metodo template puoi definire il boilerplate per accettare un Function , che viene poi passato ogni riga da un ResultSet . Ma preferirei andare con qualcosa che ha una vasta base di utenti.

    
risposta data 22.04.2017 - 22:42
fonte

Leggi altre domande sui tag