java - 如何避免在 Java 中具有相同方法主体但返回类型不同的重复代码?

标签 java hibernate oop generics code-duplication

理念:
当我使用 hibernate 时,我看到每次我必须编写某种代码。因此,我将它们移至另一种方法作为包装器。哪里会有功能接口(interface)作为参数,以便我可以在这些上下文方法中附加一些代码。
问题:
这是我的两种方法。一个返回 Object,而另一个返回 List。我如何才能将这两种方法准确地泛化并将其合二为一,这样我就可以避免代码重复。

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;
}
为了更好地理解,这是我的整个类(class)。如果有人可以建议我任何更好的方法,我将非常感激。最近几天我一直在研究这个。
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();
        }
    }
}
稍后我在 BaseDaoImpl.java 中扩展了 QueryExecutionContext。所以我需要知道两件事。
  • 我的方法是否可以。我使用纯 hibernate ,没有别的。这里没有 Spring Boot 。
  • 如果是这样,请告诉我如何解决 objectReturnContext() 和 listReturnContext() 方法中的代码重复问题。
  • 最佳答案

    Object/List<T>参数可以是通用参数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将根据 function 进行推断你传入方法。如果你这样称呼它:
    Object o = returnContext(s -> {
        ...
        return new Object(); // just an example
    });
    
    然后UObject .
    如果你这样称呼它:
    List<T> list = returnContext(s -> {
        ...
        return new ArrayList<T>(); // just an example
    });
    
    然后UArrayList<T> .

    关于java - 如何避免在 Java 中具有相同方法主体但返回类型不同的重复代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64172046/

    相关文章:

    c++ - 析构函数调用的次数比我预期的多

    java - Apache POI : garbage collection does not free memory [Java]

    java - 为什么 JFrame 颜色会通过更改内容 Pane 颜色来改变?

    spring - 创建 EntityManagerFactory 时出现异常 - 在 SerialContext 中查找 'persistence/myPU' 失败

    Hibernate,按组合键的属性查询

    Javascript OOP 原型(prototype)函数返回未定义

    java - classnotfoundException 获取如果我在成功下载后启动动态模块中的 Activity

    java - 使用 @Value 会产生 UnsatisfiedDependencyException

    string - 将实体中的列表转换为数据库中的单个字符串列

    java - 静态和动态类加载?