programing

스프링 - 현재 스레드에 실제 트랜잭션을 사용할 수 있는 EntityManager가 없음 - '영속' 호출을 안정적으로 처리할 수 없음

goodjava 2023. 1. 14. 09:23

스프링 - 현재 스레드에 실제 트랜잭션을 사용할 수 있는 EntityManager가 없음 - '영속' 호출을 안정적으로 처리할 수 없음

Spring MVC 웹 응용 프로그램에서 엔티티 모델을 데이터베이스에 저장하기 위해 "persist" 메서드를 호출하려고 하면 이 오류가 발생합니다.이 특정 오류와 관련된 게시물 또는 페이지를 인터넷에서 찾을 수 없습니다.Entity Manager Factory bean에 문제가 있는 것 같습니다만, 저는 Spring Programming에 익숙하지 않기 때문에, Web상의 다양한 튜토리얼 기사에 의하면, 모든 것이 정상적으로 초기화되고 있는 것 같습니다.

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
 http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/jdbc
  http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
  http://www.springframework.org/schema/data/jpa
  http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
  http://www.springframework.org/schema/data/repository
  http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
  http://www.springframework.org/schema/jee
  http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">

    <context:component-scan base-package="wymysl.Controllers" />
    <jpa:repositories base-package="wymysl.repositories"/> 
    <context:component-scan base-package="wymysl.beans" /> 
    <context:component-scan base-package="wymysl.Validators" /> 
    <bean
     class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
     <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>

     <bean id="passwordValidator" class="wymysl.Validators.PasswordValidator"></bean>

     <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="system" />
        <property name="password" value="polskabieda1" />
    </bean>

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml" />
    <property name="dataSource" ref="dataSource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
            <property name="showSql" value="true" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">10</prop>
        </props>
    </property>
</bean>

    <mvc:annotation-driven />

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
</bean>

    <bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
             <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/jsp/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/resources/*" location="/resources/css/"  
    cache-period="31556926"/>



</beans>

Register Controller.java

@Controller
public class RegisterController {

    @PersistenceContext
    EntityManager entityManager;

    @Autowired
    PasswordValidator passwordValidator;

    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(passwordValidator);
    }

    @RequestMapping(value = "/addUser", method = RequestMethod.GET)
    public String register(Person person) {


        return "register";

    }

    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String register(@ModelAttribute("person") @Valid @Validated Person person, BindingResult result) {
        if(result.hasErrors()) {
            return "register";
        } else {
            entityManager.persist(person);
            return "index";

        }




    }

도 같은 그 .@Transactional그리고 그것은 성공하였다.

업데이트: 기본적으로는 Persistence Context가 Transaction 유형인 것처럼 보이는 스프링 문서를 확인합니다.그래서 이 메서드는 트랜잭션 방식이어야 합니다(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html):

@PersistenceContext 주석에는 옵션 속성 유형이 있으며 기본적으로 PersistenceContextType이 됩니다.거래.이 기본값은 공유 Entity Manager 프록시를 수신하기 위해 필요한 것입니다.대체 Persistence Context Type.EXTENDED는 전혀 다른 문제입니다.그 결과, 이른바 확장 엔티티 매니저가 됩니다.이는 스레드 세이프가 아니기 때문에 스프링 관리 싱글톤빈 등의 동시에 액세스되는 컴포넌트에서는 사용할 수 없습니다.Extended Entity Manager는 예를 들어 세션에 상주하는 스테이트풀 컴포넌트에서만 사용되어야 하며 Entity Manager의 라이프 사이클은 현재 트랜잭션에 얽매이지 않고 애플리케이션에 완전히 의존합니다.

스프링 데이터 저장소에서 deleteBy 커스텀 메서드를 사용하려고 할 때 이 예외가 발생했습니다.JUnit 테스트 클래스에서 작업이 시도되었습니다.

하는 것은 .@TransactionalJUnit JUnit 。

이 실수로 3일 동안 속아넘어갔지만, 내가 직면한 상황에서도 같은 오류가 발생했습니다.제가 찾을 수 있는 모든 조언에 따라, 저는 설정을 가지고 놀았지만 소용이 없었습니다.

결국 그 차이를 알게 되었습니다.실행하고 있던 서비스는 공통의 항아리에 포함되어 있었습니다.이 문제는 Aspect J가 서비스의 인스턴스화를 동일하게 취급하고 있지 않다는 것입니다.실제로 프록시는 메서드 호출 전에 모든 일반 스프링 매직이 실행되지 않고 기본 메서드를 호출하고 있었습니다.

마지막으로 예시와 같이 서비스에 @Scope 주석을 붙이면 문제가 해결됩니다.

@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
@Transactional
public class CoreServiceImpl implements CoreService {
    @PersistenceContext
    protected EntityManager entityManager;

    @Override
    public final <T extends AbstractEntity> int deleteAll(Class<T> clazz) {
        CriteriaDelete<T> criteriaDelete = entityManager.getCriteriaBuilder().createCriteriaDelete(clazz);
        criteriaDelete.from(clazz);
        return entityManager.createQuery(criteriaDelete).executeUpdate();
    }

}

제가 게시한 방법은 삭제 방식이지만 주석이 모든 지속성 방법에 동일한 방식으로 영향을 미칩니다.

이 게시물이 항아리에서 서비스를 로드할 때 같은 문제로 어려움을 겪었던 다른 사람에게 도움이 되었으면 합니다.

boardRepo.deleteByBoardId(id);

같은 문제에 직면했다.javax.persistence를 취득했습니다.TransactionRequiredException: 현재 스레드에 사용할 수 있는 실제 트랜잭션이 있는 EntityManager가 없습니다.

컨트롤러/서비스 위에 @Transactional 주석을 추가하여 해결했습니다.

XML에서 Java 구성으로 전환했기 때문에 동일한 오류가 발생하였습니다.

가 이주한 것이 이주한 <tx:annotation-driven/>이치노

그래서 덧붙였습니다.@EnableTransactionManagement여기에 제시된 바와 같이 @Configuration Class에서 봄에 주석 기반 트랜잭션을 설정하고 지금 작동합니다.

의 추가org.springframework.transaction.annotation.Transactional시험 수업 시간에 대한 학급 수준의 주석이 문제를 해결했다.

메토드에 @Transactional을 추가해야 합니다.

도 같은 했습니다.tx:annotation-drivenapplicationContext.xml그리고 그것은 성공하였다.

동일한 컴포넌트 내의 비거래 메서드에서 이미 트랜잭션 주석된 메서드에 액세스할 때 동일한 오류가 발생했습니다.

Before:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          executeQuery(); //<-- Wrong
        }
    }

    //In another bean:
     marketObserver.startObserving();

실행을 호출하여 오류를 수정했습니다.자기 참조 컴포넌트의 Query():

Fixed version:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Autowired
        private GenericApplicationContext context;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          context.getBean(MarketObserver.class).executeQuery(); //<-- Works
        }
    }

도난 오류에 대한 답을 찾는 다른 사용자를 위한 참고 사항입니다.또 다른 일반적인 문제는 다음과 같습니다.

수 없습니다.@transactional같은 클래스 내에서 메서드를 사용합니다.

(Aspect J를 사용하는 방법이나 방법은 있지만 리팩터링이 훨씬 쉬워집니다)

때문에 @transactional★★★★★★★★★★★★★★★★★★.

가지고 계신 경우

@Transactional // Spring Transactional
class MyDao extends Dao {
}

슈퍼클래스

class Dao {
    public void save(Entity entity) { getEntityManager().merge(entity); }
}

그리고 네가 전화하면

@Autowired MyDao myDao;
myDao.save(entity);

Spring Transaction을 받을 수 없습니다.인터셉터(트랜잭션을 제공합니다).

필요한 것은 다음과 같습니다.

@Transactional 
class MyDao extends Dao {
    public void save(Entity entity) { super.save(entity); }
}

믿을 수 없지만 사실이야

@Transactional Annotation을 사용하지 않으면 DB에서 엔티티를 찾은 후 DB에서 얻은 엔티티를 제거하는 것과 동일한 목표를 달성할 수 있습니다.

Crud Repositor -> 무효 삭제(T var1);

이 문제는 여러 구성 파일에서 동일한 컨텍스트 설정으로 귀결되었습니다.여러 구성 파일에 다음 항목이 중복되지 않았는지 확인합니다.

<context:property-placeholder location="classpath*:/module.properties"/>
<context:component-scan base-package="...." />

에러 코드를 사용했을 때도 같은 에러 코드가 있었습니다.@Transaction★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

methodWithANumberOfDatabaseActions() { 
   methodA( ...)
   methodA( ...)
}

@Transactional
void methodA( ...) {
  ... ERROR message
}

나는 그 부분을 배치해야 했다.@Transactional 바로 methodWithANumberOfDatabaseActions()

이것으로 제 경우는 에러 메세지가 해결되었습니다.

는 이미 그 약을.@Transactional하지만 여전히 효과가 없었어요결국엔 평행성을 없애야 했죠

만약 당신이 병행해서 일을 하고 있다면, 하지 마세요.

모드를 삭제했습니다.

<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />

이 일을 가능하게 하다

며칠 동안 이 문제가 있었지만 온라인에서는 아무런 도움이 되지 않았습니다.다른 사람에게 도움이 될지도 모르기 때문에 여기에 답변을 올립니다.

제 경우 리모트를 통해 호출되는 마이크로 서비스 작업을 하고 있었는데, 서비스 수준의 @Transactional 주석이 리모트 프록시에 의해 픽업되지 않았습니다.

서비스 계층과 dao 계층 사이에 위임 클래스를 추가하고 위임 메서드를 트랜잭션으로 표시하면 문제가 해결되었습니다.

이것은 우리에게 도움이 되었고, 아마도 미래에 다른 사람들에게 도움이 될 것이다. @Transaction과 같이 되었습니다.

@ConditionalOnMissingClass("org.springframework.orm.jpa.JpaTransactionManager")

JPA Spring JPA 시 하였습니다.deleteAll()Junit 스 jun jun jun jun jun jun jun jun jun jun jun 。는 ★★★★★★★★★★★★★★★를 사용했습니다.deleteInBatch()&deleteAllInBatch()완벽하게 작동합니다.는 안 돼요.@Transactional츠키노

사람은 메서드를 했습니다.method1뭇매를 치다method1에 또 인 방법이라고 .method2같은 반에 속합니다. method2 있었다@Transactionalmethod1그렇지 않았다. 모든 것method1는 몇 호출했습니다.method2DB db db db db db db 。

하고 나서 되었습니다. 가가해해 해다다다다다@Transactional을 붙일 수 있습니다.method1.

이유는 잘 모르겠지만, 이건 내게는 효과가 있었어.

저장소 메서드를 호출하는 것은 @Component를 사용하여 클래스 내에서 호출되고 해당 메서드를 해당 클래스에서 삭제하고 @Service를 사용하여 다른 메서드에 배치하는 것입니다.

테스트에서 이 문제를 해결하려면 또는 @AutoConfigureTestDatabase를 사용합니다.

이는 마치 공유 엔티티 매니저를 취득할 때 사용하는 것과 같습니다.즉, 스프링을 지속하기 위해서는 이 엔티티 매니저의 빈이 공유 빈이라는 것을 알 수 있습니다.데이터 지속이 완료되지 않을 때까지 이 빈을 보유해야 합니다.따라서 @Transactional을 사용하여 persistency를 시작하고 persistency를 커밋해야 합니다.데이터 또는 작업이 완전히 저장되거나 완전히 롤백됩니다.

언급URL : https://stackoverflow.com/questions/32269192/spring-no-entitymanager-with-actual-transaction-available-for-current-thread