Exceptions in java: how reduce repeated code

Ommadawn :

I'm using a Data Access Object (DAO) pattern in Java and I have the same piece of code repeated all over my files. The thing is somethimng like this:

public User getById(int id) throws BDException {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
        query.setString("id", id);
        User user = (User) query.uniqueResult();
        tx.commit();

        return user;
    }
    catch(javax.validation.ConstraintViolationException | org.hibernate.exception.ConstraintViolationException cve) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw new BDException(cve);
    }
    catch(RuntimeException ex) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw ex;
    }
    catch(Exception ex) {
        try {
            if(tx.getStatus() == TransactionStatus.ACTIVE) {
                tx.rollback();
            }
        }
        catch(Exception exc) {
            LOGGER.error("Error rollback in method='" + getMethodName() + "'");
        }
        throw new RuntimeException(ex);
    }
}

Well, I want you to look at the catch's part. I have it repeated in every method I have. If it was simple code, I could create a method, put all that code inside and call the method instead of repeat the code. The problem is that it is not normal code, they are exceptions.

So, is there any solution to reuse code and not to repeat (copy-pasting) the code in every method?

Thanks!

VoiceOfUnreason :

is there any solution to reuse code and not to repeat (copy-pasting) the code in every method?

There is.

The "meat" of your function is here

    Query query = session.createQuery("SELECT u FROM User u WHERE u.id=:id");
    query.setString("id", id);
    User user = (User) query.uniqueResult();

If you squint very carefully, you may see that this is a "function" that accepts a Session as an argument, and returns a User. What you can then do is make this function an argument to the thing that does all of the exception handling.

In Java, that usually means expressing the function as an "object"

User MyCrazyFunctionThing::uniqueResult(Session session) {
    Query query = session.createQuery(this.sql);
    query.setString("id", this.id);
    return query.uniqueResult();
}

User DatabaseGateway::execute(MyCrazyFunctionThing q) {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        User user = q.uniqueResult(session)
        tx.commit();

        return user;
    } catch (...) {
        // ...
    }
}

Right away, you can turn that into logic that can be run any time you try to fetch a unique user from a session.

You can make that even more general with generics

interface MyCrazyGenericThing<T> {
    T uniqueResult(Session session);
}

class MyCrazyFunctionThing implements MyCrazyGenericThing<User> {
    User uniqueResult(Session session) {
        Query query = session.createQuery(this.sql);
        query.setString("id", this.id);
        return query.uniqueResult();
    }
}

<T> T DatabaseGateway::execute(MyCrazyGenericThing<T> q) {
    Session session = sessionFactory.getCurrentSession();
    Transaction tx = session.getTransaction();

    try {
        tx.begin();
        T result = q.uniqueResult(session)
        tx.commit();

        return result;
    } catch (...) {
        // ...
    }
}

What you are seeing here is the Strategy Pattern being used to specify what code should run inside the transaction logic.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=74758&siteId=1