programing

Spring boot + Hibernate + JPA 트랜잭션 Entity Manager를 사용할 수 없습니다.

bestprogram 2023. 10. 4. 22:14

Spring boot + Hibernate + JPA 트랜잭션 Entity Manager를 사용할 수 없습니다.

스프링부츠 1.2.3을 사용하고 있습니다.동면 상태에서 JPA가 적용된 릴리스 버전.다음과 같은 예외가 있습니다.

org.springframework.dao.InvalidDataAccessApiUsageException: No transactional EntityManager available; nested exception is javax.persistence.TransactionRequiredException: No transactional EntityManager available
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:410) ~[EntityManagerFactoryUtils.class:4.1.6.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223) ~[HibernateJpaDialect.class:4.1.6.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) ~[AbstractEntityManagerFactoryBean.class:4.1.6.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[ChainedPersistenceExceptionTranslator.class:4.1.6.RELEASE]
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) ~[DataAccessUtils.class:4.1.6.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) ~[PersistenceExceptionTranslationInterceptor.class:4.1.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122) ~[CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.class:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [ExposeInvocationInterceptor.class:4.1.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [ReflectiveMethodInvocation.class:4.1.6.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [JdkDynamicAopProxy.class:4.1.6.RELEASE]
at com.sun.proxy.$Proxy110.deleteByCustomerId(Unknown Source) ~[na:na]

Caused by: javax.persistence.TransactionRequiredException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:275) ~[SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.class:4.1.6.RELEASE]
at com.sun.proxy.$Proxy102.remove(Unknown Source) ~[na:na]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$DeleteExecution.doExecute(JpaQueryExecution.java:270) ~[JpaQueryExecution$DeleteExecution.class:na]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:74) ~[JpaQueryExecution.class:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:97) ~[AbstractJpaQuery.class:na]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:88) ~[AbstractJpaQuery.class:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:395) ~[RepositoryFactorySupport$QueryExecutorMethodInterceptor.class:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:373) ~[RepositoryFactorySupport$QueryExecutorMethodInterceptor.class:na]

다음은 저의 프로그램 구조입니다.
구성 클래스

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableTransactionManagement
public class WSApplication {
    public static void main(final String[] args) {
        SpringApplication.run(WSApplication.class, args);
    }
}

@Entity
@Table(Orders)
public class Order {
    @id
    @GeneratedValue
    private long id;

    @Column(name = "customerId")
    private Long customerId;

    // getter & setter methods
    // equals & hashCode methods
}

public interface OrderRepository extends JpaRepository<Order, Long> {

    List<Order> findByCustomerId(Long customerId);

    // 4- @Transactional works fine
    void deleteByCustomerId(Long cusotmerId);

}

public class OrderService {

    @Autowired
    private OrderRepository repo;

    // 3- @Transactional works fine
    public void deleteOrder(long customerId){
        //1- throws exception
        repo.deleteByCustomerId(customerId); 

        //2- following works fine
        //repo.delete(repo.findByCustomerId(customerId).get(0));
    }

}

위의 서비스 클래스 코드에서, 왜 2개의 작동과 1개의 던지기 예외인지 안내해 줄 수 있는 사람이 있습니까?

감사해요.

먼저, 나는 스프링-데이터 JPA 문서를 인용하여 왜 그 이유를 정당화합니다.delete방법은 당신의 경우에 효과가 있습니다(옵션 2를 의미합니다).

리포지토리 인스턴스의 CRUD 메서드는 기본적으로 트랜잭션입니다.읽기 작업의 경우 트랜잭션 구성readOnly플래그가 true로 설정되어 있고, 다른 모든 플래그는 일반으로 구성되어 있습니다.@Transactional기본 트랜잭션 구성이 적용되도록 합니다.자세한 내용은 CrudRepository의 JavaDoc 참조

deletemethod는 사실 method입니다.CrudRepository. 저장소 확장JpaRepository확장되는CrudRespository, 따라서 이것은 CrudRepository 인터페이스에 속하며 위의 인용문에 따르면 트랜잭션입니다.

Transactional Query Method 섹션을 읽어보면 옵션 4가 동일하고 저장소의 모든 메서드에 사용자 지정 트랜잭션 동작을 적용하는 방법을 알 수 있습니다.또한 문서의 예제 61은 옵션 3과 동일한 시나리오를 보여줍니다.

이제 JDBC 로직을 사용하는 것이 아니라 데이터베이스가 트랜잭션을 처리하는 ORM 기반 프레임워크 내에서 작업한다는 점을 명심하십시오.ORM 프레임워크는 개체 캐시와 데이터베이스 간의 동기화를 트리거하려면 트랜잭션이 필요합니다.따라서 당신은 ORM 논리를 수행하는 방법에 대해 알고 트랜잭션 컨텍스트를 제공해야 합니다.deleteByCustomerId.

기본적으로@Transactional(즉, 매개변수 없이) 전파 모드를 다음으로 설정합니다.REQUIREDfalse로 플래그만 읽습니다.내부에 주석이 달린 메서드를 호출하면 트랜잭션이 없는 경우 트랜잭션이 초기화됩니다.이것이 @LucasSaldanha(여러 저장소 호출에 대한 트랜잭션을 정의하는 facade 사용 예제와 동일) 및 옵션 4해결 방법이 작동하는 이유입니다.그렇지 않으면 거래가 없으면 옵션 1의 던져진 예외에 해당합니다.

네, 효과를 낼 수 있는 방법을 찾았습니다.

만 넣어주세요.@Transactional주석(org. 스프링 프레임워크. 트랜잭션. annot)주문 서비스deleteOrder 메서드에서 트랜잭션).

@Transactional
public void deleteOrder(long customerId){
    repo.deleteByCustomerId(customerId);
}

두번째가 왜 효과가 있는지 정말 모르겠어요.CrudRepository 인터페이스에서 직접적인 방법이기 때문에 원자적으로 실행하는 방법을 알고 있다고 생각합니다.

앞의 것은 deleteByCustomerId에 대한 호출입니다.이 호출은 지정된 ID를 가진 고객을 찾기 위해 처리된 후 삭제됩니다.어떤 이유에서인지 그것은 명시적인 거래를 이용합니다.

다시 말하지만 그것은 그저 추측일 뿐입니다.스프링 개발자에게 연락해서 이 동작을 확인하기 위한 문제를 열어보겠습니다.

도움이 되길 바랍니다!

참조 : http://spring.io/guides/gs/managing-transactions/

도가 요.No transactional EntityManager available외에 예외.search()을 지정합니다.@Transactional.

Spring Boot에서 Hibernate 검색을 설정하는 방법을 설명하는 이 자습서를 따릅니다.

는 이었습니다에 의존도가 였습니다.hibernate-search-orm에게 별 은. 저에게 별 문제없이 작용한 의존성은

compile("org.hibernate:hibernate-search-orm:5.7.0.Final")

그래들 빌드 파일에 이것을 추가한 후 모든 것이 예상대로 작동했습니다.

이것이 다른 사람에게도 도움이 되길 바랍니다.

SimpleJpaRepository 클래스 - Spring이 리포지토리 인터페이스에 대한 구현을 제공하는 데 사용하는 기본 클래스입니다.그리고 클래스를 확인하면 호출되는 함수가 @Transactional 을 가지는 것을 알 수 있습니다.

@Override
    @Transactional
    public void deleteAllById(Iterable<? extends ID> ids) {

        Assert.notNull(ids, "Ids must not be null!");

        for (ID id : ids) {
            deleteById(id);
        }
    }

언급URL : https://stackoverflow.com/questions/31127309/spring-boot-hibernate-jpa-no-transactional-entitymanager-available