Дублирующий код внутри двух разных реализаций интерфейса - PullRequest
0 голосов
/ 10 февраля 2019

Для каждого объекта я создаю контроллер, сервис и DAO.У меня сейчас около 8 объектов с этими классами.Давайте возьмем, например, мои классы Categorie и Product.

Класс CategorieDaoImpl реализует методы из CategorieDao

@Override
public boolean insertCategorie(Categorie categorie) {
    Session session = null;
    try {
        session = super.getConnection();
        session.getTransaction().begin();
        session.save(categorie);
        session.getTransaction().commit();
        return true;
    } catch (HibernateException e) {
        e.printStackTrace();
        return false;
    } finally {
        closeConnection(session);
    }
}

Класс ProductDaoImpl реализует методы из ProductDao

@Override
public boolean insertProduct(Product product) {
    Session session = null;
    try {
        session = super.getConnection();
        session.getTransaction().begin();
        session.save(product);
        session.getTransaction().commit();
        return true;
    } catch (HibernateException e) {
        e.printStackTrace();
        return false;
    }
    finally {
        closeConnection(session);
    }
}

Как видите, код двух классов довольно схож, кроме параметров и параметров save().

Intellij говорит мне, что это дубликаткод, но он не дает мне решения, как обычно, когда дублирующий код находится внутри класса.Любая идея, как я могу решить эту проблему и сделать ее лучше?

Заранее спасибо.

РЕДАКТИРОВАТЬ:

Большинство классов Дао имеют те же методы CRUS: получить, вставить, обновить, удалить.Чаще всего отличается только параметр.

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Вы можете решить проблему с помощью AbstractInsertable<T> -класса, в котором есть некоторый public boolean insert(T t), содержащий ваш код:

public abstract class AbstractInsertable<T> extends ... {
    public boolean insert(T t) {
        Session session = null;
        try {
            session = super.getConnection();
            session.getTransaction().begin();
            session.save(t);
            session.getTransaction().commit();
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
            return false;
        } finally {
            closeConnection(session);
        }
    }

    [...]
}

Реализации затем могут наследоваться от этого AbstractInsertable<T>, например CategorieDaoImpl extends AbstractInsertable<Category>.Это, конечно, работает только до тех пор, пока вы наследуете только от одного класса.

Другой альтернативой будет работа с интерфейсами и реализациями по умолчанию.

Ответ на этом заканчивается.Остальное мое личное мнение.


Мое личное желание было бы для Java разрешить множественное наследование для этих точных проблем: вы могли бы определить classs для каждой CRUD-операции и использовать их как миксины в Dao -implementations.Методы по умолчанию в интерфейсах довольно близки к мульти-наследованию, но имеют некоторые ограничения, например, все методы должны быть public, а атрибуты не могут быть определены, чего не было бы при мульти-наследовании.


Незначительное замечание в вашем коде: у вас есть возможность возникновения NullPointerException:

        Session session = null;
        try {
            session = super.getConnection();
            [...]
        } finally {
            closeSession(session);
        }

Не зная точной реализации closeSession(...), я не удивлюсь, если вы не выполняетеnullcheck, таким образом, NPE может быть брошено.Если Session является AutoCloseable, вы можете использовать try-with-resources.Если это не так, вы можете использовать Optional в своих интересах:

        Optional<Session> optionalSession = Optional.empty();
        try {
            optionalSession = Optional.of(super.getConnection());
            session = optionalSession.get();
            [...]
        } finally {
            optionalSession.ifPresent(this::closeSession);
        }
0 голосов
/ 10 февраля 2019

Самое простое решение было бы:

public boolean insertGeneric(Object whatever) {
    Session session = null;
    try {
        session = super.getConnection();
        session.getTransaction().begin();
        session.save(whatever);
        session.getTransaction().commit();
        return true;
    } catch (HibernateException e) {
        e.printStackTrace();
        return false;
    } finally {
        closeConnection(session);
    }
}

Конечно, более "общий ответ" мог бы заключаться в том, что вы используете какой-то параметр типа <T extends some BaseType> вместо Object.

Если такого базового класса нет, следующим лучшим вариантом будет определить общий базовый интерфейс или что-то, что все объекты, которые вы намереваетесь сохранить, могли бы / должны / должны реализовать.

Другими словами: ваш вариантпространство во многом зависит от фактической подписи session.save()!

...