Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid duplicate code with the same method body but different return types in Java?

The Idea:

When I was using hibernate I saw that everytime I had to write some sort of code. So I moved them to another method as wrapper. Where there will be functional interface as argument so that I can append some code in those context methods.

Problem:

Here is my two methods. One returns Object while another one is returning List. How can I exactly generify and make those two methods as one so that I can avoid code duplication.

public Object objectReturnContext(Function<Session, Object> function) {
    Object object = null;
    Transaction transaction = null;

    try {
        Session session = HibernateUtil.sessionFactory().getCurrentSession();
        transaction = session.beginTransaction();
        object = function.apply(session);
        transaction.commit();
    } catch (NoResultException exception) {
        if (transaction != null) transaction.rollback();
        return object;
    } catch (HibernateException exception) {
        if (transaction != null) transaction.rollback();
        exception.getStackTrace();
    }

    return object;
}


public List<T> listReturnContext(Function<Session, List<T>> function) {
    List<T> object = null;
    Transaction transaction = null;

    try {
        Session session = HibernateUtil.sessionFactory().getCurrentSession();
        transaction = session.beginTransaction();
        object = function.apply(session);
        transaction.commit();
    } catch (NoResultException exception) {
        if (transaction != null) transaction.rollback();
        return object;
    } catch (HibernateException exception) {
        if (transaction != null) transaction.rollback();
        exception.getStackTrace();
    }

    return object;
}

For better understanding, This is my whole class. If anyone can advice me any better way I will be very thankful. I have been into this for last few days.

package com.go_task.database;


import javax.persistence.Table;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;


public abstract class QueryExecutionContext <T> {

    public Class<T> entity;
    public String tableName;

    public QueryExecutionContext(Class<T> entity) {
        this.entity = entity;
        this.tableName = entity.getAnnotation(Table.class).name();
    }

    public List<T> criteriaContext(CriteriaContextRunner<Session, Root<T>,
            CriteriaQuery<T>, CriteriaBuilder, List<T>> runner) {
        List<T> data = new ArrayList<>();
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.sessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            CriteriaQuery<T> criteriaQuery =
                    criteriaBuilder.createQuery(entity);
            Root<T> root = criteriaQuery.from(entity);
            data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
            transaction.commit();
        } catch (HibernateException exception) {
            if (transaction != null) transaction.rollback();
            exception.getStackTrace();
        }

        return data;
    }

    public Object singleCriteriaContext(CriteriaContextRunner<Session, Root<T>,
            CriteriaQuery<T>, CriteriaBuilder, Object> runner) {
        Object data = null;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.sessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
            CriteriaQuery<T> criteriaQuery =
                    criteriaBuilder.createQuery(entity);
            Root<T> root = criteriaQuery.from(entity);
            data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
            transaction.commit();
        } catch (HibernateException exception) {
            if (transaction != null) transaction.rollback();
            exception.getStackTrace();
        }

        return data;
    }

    public Object objectReturnContext(Function<Session, Object> function) {
        Object object = null;
        Transaction transaction = null;
    
        try {
            Session session = HibernateUtil.sessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            object = function.apply(session);
            transaction.commit();
        } catch (NoResultException exception) {
            if (transaction != null) transaction.rollback();
            return object;
        } catch (HibernateException exception) {
            if (transaction != null) transaction.rollback();
            exception.getStackTrace();
        }
    
        return object;
    }
    
    public List<T> listReturnContext(Function<Session, List<T>> function) {
        List<T> object = null;
        Transaction transaction = null;
    
        try {
            Session session = HibernateUtil.sessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            object = function.apply(session);
            transaction.commit();
        } catch (NoResultException exception) {
            if (transaction != null) transaction.rollback();
            return object;
        } catch (HibernateException exception) {
            if (transaction != null) transaction.rollback();
            exception.getStackTrace();
        }
    
        return object;
    }

    public void noReturnContext(Consumer<Session> consumer) {
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.sessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            consumer.accept(session);
            transaction.commit();
        } catch (HibernateException exception) {
            if (transaction != null) transaction.rollback();
            exception.getStackTrace();
        }
    }
}

I have extented QueryExecutionContext in my BaseDaoImpl.java later on. So I need to know 2 things.

  1. Is my approch is ok or not. Im using pure hibernate and nothing else. No spring boot here.
  2. If so then tell me how can I solve the code duplication in objectReturnContext() and listReturnContext() method.
like image 300
Farhat Shahir Avatar asked Jan 25 '23 17:01

Farhat Shahir


1 Answers

The Object/List<T> parameter could be a generic parameter U:

public <U> U returnContext(Function<Session, U> function) {
    U object = null;
    Transaction transaction = null;

    try {
        Session session = HibernateUtil.sessionFactory().getCurrentSession();
        transaction = session.beginTransaction();
        object = function.apply(session);
        transaction.commit();
    } catch (NoResultException exception) {
        if (transaction != null) transaction.rollback();
        return object;
    } catch (HibernateException exception) {
        if (transaction != null) transaction.rollback();
        exception.getStackTrace();
    }

    return object;
}

U will be inferred depending on what function you pass into the method. If you call it like:

Object o = returnContext(s -> {
    ...
    return new Object(); // just an example
});

Then U is Object.

If you call it like:

List<T> list = returnContext(s -> {
    ...
    return new ArrayList<T>(); // just an example
});

Then U is ArrayList<T>.

like image 134
Sweeper Avatar answered Jan 30 '23 00:01

Sweeper