Дублирующий код внутри двух разных реализаций интерфейса
Для каждого объекта я делаю контроллер, сервис и 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 говорит мне, что это дублирующий код, но не дает мне решения, как обычно, когда дублирующий код находится внутри класса. Любая идея, как я могу решить это и сделать это лучше?
Заранее спасибо.
РЕДАКТИРОВАТЬ:
Большинство классов Dao имеют одинаковые методы CRUS: получить, вставить, обновить, удалить. В основном, только параметр отличается.
2 ответа
Вы можете решить проблему с 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(...)
Я не удивлюсь, если вы не выполняете проверку на ноль, таким образом 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);
}
Самым простым решением будет:
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()
!