0

In Spring Boot application with HikariCP dataSource I've execute HQL queries with helper class:

public class QueryExecutor {
    private Session session;

    @Autowired
    private SessionFactory sessionFactory;

    public QueryExecutor getConnection() {
        session = sessionFactory.openSession();
        session.beginTransaction();

        return this;
    }

    public void closeConnection() {
        session.getTransaction().commit();
        session.close();
    }

    public List execute(String hql, Long limit, Long offset) {
        getConnection();

        Query query = session.createQuery(hql);

        List list = query.list();

        closeConnection();

        return list;
    }

It works ok, but when I start using class widely, application starts freezes because Hibernate Session is closed randomly and transaction wait 30 seconds (default timeout value for HikariCP transactions) before get Session is closed error (or currentPersistenceContext is null if I used getCurrentSession() instead openSesssion()).

First of all, I changed open session to getCurrentSession function. But I also need to specify context with @PersistenceContext or hibernate.current_session_context_class=thread in hibernate.cfg.xml. I read that this property better to use with default value. Also I specify hibernate.connection.release_mode=AFTER_TRANSACTION. But that isn't solve a problem.

After all, I changed class like that:

@PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public List execute(String hql, Long limit, Long offset) {
        Query query = entityManager.createQuery(hql);    
        return query.getResultList();
    }

and use javax.persistence.Query instead Hibernate queries. Now it works ok. But is that a correct modifications? All functions worked with execute method of QueryExecutor annotated with @Transactional. As I uderstood, in that case no beginTransaction() needed. But need I close entityManager after execute() ?

SessionFactory used with Hibernate without JPA and EntityManager used with Hibernate JPA technologies?

How can I solve problem without using EntityManager?

Meteo ir3
  • 449
  • 8
  • 21

1 Answers1

1

You don't need to close transactions manually if you use @Transactional annotation.

But if you use it, I will reccomend you try to use JPA Repositories and wrap in @Transactional annotation the methods of business logic only.

In which case you will no longer need EntityManager and you will be able to create custom complex queries with JpaSpecificationExecutor and JPA Criteria API Queries.

Artiow
  • 351
  • 1
  • 9
  • I'm already using CrudRepository. And what about closing entityManager after query execution? – Meteo ir3 Sep 26 '18 at 06:26
  • No, you do not need to do this. _The lifecycle of entity manager obtained using @PersistenceContext annotation is managed by container itself_. Check [this](https://www.javabullets.com/access-entitymanager-spring-data-jpa/) and [this](http://www.thejavageek.com/2014/02/24/transaction-scoped-entitymanager/) links. – Artiow Sep 26 '18 at 06:55
  • Also, once again, you do not need to execute queries manually if you use [Spring Data](https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html). – Artiow Sep 26 '18 at 07:08
  • But if you want it, you can do this with annotation [`@Query`](https://www.baeldung.com/spring-data-jpa-query), without using `EntityManager`. – Artiow Sep 26 '18 at 07:18
  • The reason why I'm using manually query execution is that I'm working on legacy sql code migration. So, I have many functions with conditionally-composed JPQL queries (like legacy sql queries) for safety migration. I can't use @Query in repositories because query string builds depends on some conditions in legacy code (query string changes). Also that functions placed on service layer, not in repository. Is that a correct approach? Or I must to move methods to repository, but what I need to do if that methods isn't fixed queries? – Meteo ir3 Sep 26 '18 at 08:18
  • Query string changes is a bad practice. Query builders must placed on service layer, but queries must built dynamically by `CriteriaBuilder`. – Artiow Sep 26 '18 at 11:39
  • CriteriaBuilder is deprecated and hql need to be used instead, as I heard. Is it so? – Meteo ir3 Sep 26 '18 at 12:18
  • No, `org.hibernate.Criteria` is deprecated, not `javax.persistence.criteria`. [Proof link](https://stackoverflow.com/questions/38448195/why-is-criteria-query-deprecated-in-hibernate-5). – Artiow Sep 26 '18 at 12:31