#java #hibernate #jpa #refactoring
#java #гибернация #jpa #рефакторинг
Вопрос:
Я создал метод update (), который использует JPA. Это выглядит следующим образом:
public boolean update(Programy program) throws Exception {
try {
entityManagerFactory = Persistence.createEntityManagerFactory("firebird_config_file");
entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.merge(program);
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
В моем методе сохранения () и удаления я меняю только одну вещь — merge () -> persist() или delete(). Оставшаяся часть кода похожа на приведенную здесь. Как я могу реорганизовать этот код, чтобы упростить это?
Ответ №1:
Это очень хороший вариант использования шаблона, называемого методом шаблона.
Например, вы можете создать абстрактный класс, который оборачивает весь ваш шаблонный код в perform
метод:
abstract public class HibernateAction<T> {
private EntityManagerFactory entityManagerFactory;
//I'm passing EntityManagerFactory, because it should be singleton and you shouldn't
//probably create it from scratch everytime
public HibernateAction(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
protected abstract T action(EntityManager entityManager, T entity);
public boolean perform(T entity) throws Exception {
try {
var entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
action(entityManager, entity); //call to action which need to be overriden
entityManager.getTransaction().commit();
entityManager.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
затем вы можете просто создать класс, который наследует HibernateAction
:
public class UpdateAction extends HibernateAction<Program> {
public UpdateAction(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
}
@Override
protected Program action(EntityManager entityManager, Program entity) {
return entityManager.merge(entity);
}
}
и, наконец, вы можете использовать его следующим образом:
public boolean update(Program program) throws Exception {
return updateAction.perform(program);
}
Но поскольку анонимные методы поддерживаются в Java (начиная с Java 8), вы также могли бы переписать его немного менее подробным способом, используя функции более высокого порядка:
public class HibernateAction2{ // no longer abstract
private EntityManagerFactory entityManagerFactory;
public HibernateAction2(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
//we expect a user to pass lambda function, which would tell us what to do with an entity manager
public boolean perform (Consumer<EntityManager> action) throws Exception {
try {
var entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
action.accept(entityManager);
entityManager.getTransaction().commit();
entityManager.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
и тогда вы можете использовать его как:
hibernateAction2.perform(em -> em.merge(program)); //for merge
hibernateAction2.perform(em -> em.persist(program)); //for persist, etc.
Это называется шаблоном заимствования или шаблоном заимствования (или скобкой на языках FP), потому что вы «заимствуете» диспетчер объектов из hibernateAction2, чтобы использовать его для выполнения какого-либо действия, но он обрабатывает все другие вещи, такие как создание объекта или закрытие соединения.