简体   繁体   中英

Hibernate JPA simplify code for update(),delete(),add()

I created update() method which is using JPA. It looks like this:

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;
        }
    }

In my save() and delete method I am changing only one thing - merge() -> persist() or delete(). Remaining part of code is similar as here. How can i refactor this code to simplify this?

This is a very good use-case for a pattern called template method .

For example, you can create an abstract class, which wraps all your boilerplate code in perform method:

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;
        }   
    }
}

then you can just create a class which inherits 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);
    }
}

and finally you can use it like this:

public boolean update(Program program) throws Exception {
    return updateAction.perform(program);
}

But since anonymous methods are supported in Java (since Java 8), you could also rewrite it in a little bit less verbose way using higher order functions:

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;
        }
    }
}

and then you can use it like:

hibernateAction2.perform(em -> em.merge(program)); //for merge

hibernateAction2.perform(em -> em.persist(program)); //for persist, etc.

This is called loan pattern or loaner pattern (or bracket in FP languages), because you "loan" entity manager from hibernateAction2 to use it to do some kind of action, but it handles all other things, like creating an object or closing connection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM