1

I am using JPA+Hibernate in my Spring Boot Application. My Service Method is as follows:-

    @Override
    public Employee createEmployee(Employee employeeModel) {
        logger.debug("entered the createEmployee method");
        Optional<Employee> optionalEmployee = repository.findByEmpShortNm(employeeModel.getEmpShortNm());
        logger.debug("Fetched the optional");
        if(optionalEmployee.isPresent())
            return optionalEmployee.get();
        else {
            logger.debug("Persisting employee.....");
            return repository.save(employeeModel);
        }
    }

EmployeeRepository.java has following method:-

@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Employee> findByEmpShortNm(String uuid);

My Application was working fine until I applied Lock annotation on my repository method. After applying Lock createEmployee method is throwing following exception:-

javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1560)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1581)
at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getSingleResult(CriteriaQueryTypeQueryAdapter.java:111)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

Why it's not able to get a transaction while it was working fine when I was not using @Lock Annoation. What's the relation b/w @Lock and Transaction.

I would appreciate if any reference can be provided.

Manish
  • 1,274
  • 3
  • 22
  • 59

1 Answers1

3

Solution: you should annotate your service with @Transactional

When the lock is explicitly enabled and there is no active transaction, the underlying JPA implementation will throw a TransactionRequiredException.

It is somehow logical when you don't have your own transaction, why do you want to lock the entity object? You should have a transaction outside repository method during which, you want to lock entity object.

Read this article:

https://www.baeldung.com/java-jpa-transaction-locks

Tashkhisi
  • 2,070
  • 1
  • 7
  • 20
  • does it mean that when we are not doing explicit lock, transaction is automatically created by JPA/Hibernate but when we are marking explicit locking we should mark with Transactional to create Transaction. – Manish Jul 29 '20 at 10:32
  • then Transactional annotation can also be applied on the same Repository method because transaction is required for do the db thing. right ? – Manish Jul 29 '20 at 10:45
  • I've just added some notes to my answer, please read it again and let me know if you have any question. – Tashkhisi Jul 29 '20 at 10:47