Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop JPA entity manager from flushing before every select

I am using JPA (with hibernate as the provider) in spring for a web-app. I have a few methods that construct a complex object to be passed to the UI. As part of theses methods flow, a few select SQL statements are executed. The problem is that the entity manager flushes before each select, this action takes a lot of time and is hindering the performance. Is there a way to prevent the entity manager from flushing before each select? (I don't care for stale data in the select selects above)

Thank you.

Here is my GenericDAO

@Repository
public abstract class GenericDAOWithJPA<T, ID extends Serializable> implements IGenericDAO<T, ID> {
    private static final int MAX_RETRIES = 3;
    private static final long WAIT_INTERVAL_MS = 1000;
    static final Logger LOG = LoggerFactory.getLogger(GenericDAOWithJPA.class);

    private Class<T> persistentClass;

    protected EntityManager entityManager;

    @SuppressWarnings("unchecked")
    public GenericDAOWithJPA() {
            this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }


    @Override
    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
        this.entityManager.setFlushMode(FlushModeType.COMMIT)
    }


    @Override
    public Class<T> getPersistentClass() {
        return persistentClass;
    }

    /* (non-Javadoc)
     * @see com.legolas.dao.IGenericDAO#find(ID)
     */
    @Override
    public T find(ID id) {
        return entityManager.find(persistentClass, id);
    }


    @Override
    public T getReference(ID id) {
        return entityManager.getReference(persistentClass, id);
    }

    /* (non-Javadoc)
     * @see com.legolas.dao.IGenericDAO#persist(T)
     */
    @Override
    public void persist(T entity) {
        entityManager.persist(entity);
    }

    @Override
    public void persist(List<T> entityList) {
        for (T entity : entityList) {
            persist(entity);
        }
    }



    @Override
    public T merge(T entity) {
        return entityManager.merge(entity);
    }


    @Override
    public void remove(T entity) {
        entityManager.remove(entity);
    }


    @Override
    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
    }


    @Override
    @SuppressWarnings("unchecked")
    public List<T> findInRange(int firstResult, int maxResults) {
        return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }


    @Override
    public long count() {
        return (Long) entityManager.createQuery("Select count(t) from " + persistentClass.getSimpleName() + " t").getSingleResult();
    }

    @Override
    public void flush() {
        this.entityManager.flush();
    }

    @Override
    public void refresh(T entity) {
        int retry = 0;
        RuntimeException lastException = null;
        do {
        try {
            this.entityManager.refresh(entity);
        } catch (OptimisticLockException e) {
            retry++;
            lastException = e;
            LOG.debug("OptimisticLockException retry {}", retry);
            try {
                Thread.sleep(WAIT_INTERVAL_MS);
            } catch (InterruptedException e1) {
                retry = MAX_RETRIES;
            }
        }
        } while (lastException != null && retry < MAX_RETRIES);

    }
}
like image 692
Noam Nevo Avatar asked Mar 01 '11 14:03

Noam Nevo


People also ask

What does EntityManager flush () do?

The EntityManager. flush() operation can be used the write all changes to the database before the transaction is committed. By default JPA does not normally write changes to the database until the transaction is committed. This is normally desirable as it avoids database access, resources and locks until required.

How do you change flush mode in Hibernate?

And if you want to use a Hibernate-specific flush mode, you need to use Hibernate's Session to create your query and call its setHibernateFlushMode method.

What is the use of flush method in JPA repository?

Unlike save(), the saveAndFlush() method flushes the data immediately during the execution. This method belongs to the JpaRepository interface of Spring Data JPA.

What is Hibernate flush?

Flushing the session forces Hibernate to synchronize the in-memory state of the Session with the database (i.e. to write changes to the database). By default, Hibernate will flush changes automatically for you: before some query executions. when a transaction is committed.


2 Answers

The following code disables flush before queries (flush would occur only before commit):

em.setFlushMode(FlushModeType.COMMIT);
like image 150
axtavt Avatar answered Nov 09 '22 17:11

axtavt


You can also set your flush mode per query. It does not have to apply to the entire entity manager.

 TypedQuery<Person> people = ... ;
 people.setFlushMode(FlushModeType.COMMIT);
like image 27
Onur Avatar answered Nov 09 '22 16:11

Onur