Getting "javax.persistence.TransactionRequiredException: no transaction is in progress" in Spring Boot Application

huangapple go评论62阅读模式
英文:

Getting "javax.persistence.TransactionRequiredException: no transaction is in progress" in Spring Boot Application

问题

我在我的Spring Boot应用程序中使用了JPA+Hibernate。我的服务方法如下所示:

@Override
public Employee createEmployee(Employee employeeModel) {
    logger.debug("进入createEmployee方法");
    Optional<Employee> optionalEmployee = repository.findByEmpShortNm(employeeModel.getEmpShortNm());
    logger.debug("获取可选的员工");
    if (optionalEmployee.isPresent())
        return optionalEmployee.get();
    else {
        logger.debug("持久化员工......");
        return repository.save(employeeModel);
    }
}

EmployeeRepository.java 有以下方法:

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

在我在存储库方法上应用了Lock注解之前,我的应用程序运行正常。但是在应用了Lock后,createEmployee方法抛出以下异常:

javax.persistence.TransactionRequiredException: 没有进行中的事务
    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)

为什么它无法获取事务,而在不使用@Lock注解时正常运行?@Lock和事务之间有什么关系?

如果有相关参考资料,我将不胜感激。

英文:

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

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

EmployeeRepository.java has following method:-

@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional&lt;Employee&gt; 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.

答案1

得分: 3

解决方案:您应该在您的服务上加上@Transactional注解。

当锁被显式启用且没有活动的事务时,底层的JPA实现将抛出TransactionRequiredException异常。

当您没有自己的事务时,为什么要锁定实体对象似乎是合乎逻辑的呢?在您想要锁定实体对象的仓库方法之外,应该有一个事务。

阅读这篇文章:

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

英文:

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

huangapple
  • 本文由 发表于 2020年7月29日 16:54:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63149900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定