복붙노트

[SPRING] entityManager를 사용하여 JPA에서 트랜잭션을 시작하는 방법

SPRING

entityManager를 사용하여 JPA에서 트랜잭션을 시작하는 방법

Spring, Hibernate, JPA, SOAP 웹 서비스를 사용하는 응용 프로그램에 대한 작업을 시작했습니다. 이제 특정 쿼리를 트랜잭션에서 실행해야한다는 요구 사항이 있습니다. 하나라도 실패하면 전체 트랜잭션이 롤백됩니다.

DAO 계층의 코드는 다음과 같습니다.

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import org.hibernate.Session;

    public class BillDAOImpl implements BillDao{

             @PersistenceContext(type = PersistenceContextType.EXTENDED)
             private EntityManager em;

             public boolean processBills() throws Exception{

             EntityTransaction tx = null;
             Session session = null;

             try{

                 session = em.unwrap(Session.class);
                 tx = em.getTransaction();

                 Bill bill = em.find(Bill.class, billId);

                 //session.beginTransaction();
                 tx.begin();
                 ...
                 ...
                 em.persist(bill);
                 ...
                 ...
                 em.merge(<other object>);
                 ...
                 ...
                 //session.getTransaction().commit();
                 tx.commit();
             } catch(){
             }

             }

    }

tx = em.getTransaction ()을 실행하면 다음과 같은 오류가 발생합니다.

java.lang.IllegalStateException: Cannot execute getTransaction() on a container-managed EntityManager

다른 트랜잭션 관련 속성은 다음과 같습니다.

<bean id="tuneEntityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:persistenceXmlLocation="classpath*:META-INF/tune-persistence.xml"
        p:persistenceUnitName="tunePersistenceUnit" p:loadTimeWeaver-ref="loadTimeWeaver"
        p:jpaVendorAdapter-ref="jpaVendorAdapter" p:jpaDialect-ref="jpaDialect"
        p:dataSource-ref="tuneDbDataSource">
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup
                </prop>
                <prop key="net.sf.ehcache.configurationResourceName">/${tune-db.ehcache.config.file}</prop>
                <prop key="hibernate.transaction.flush_before_completion">false</prop>              
                <prop key="hibernate.default_schema">${tune-db.schema}</prop>
                <prop key="org.hibernate.envers.default_schema">${tune-db.schema}</prop>
                <prop key="javax.persistence.validation.mode">${tune-db.data.validation}</prop>
                <prop key="hibernate.connection.isolation">3</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
                <prop key="hibernate.show_sql">${tune-db.hibernate.show-sql}</prop>
                <prop key="hibernate.format_sql">${tune-db.hibernate.format-sql}</prop>
            </props>
        </property>     
    </bean>

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

session.beginTransaction () 및 session.getTransaction (). commit ()을 사용하면 올바르게 작동합니다.

그러나 그것을 entityManager의 트랜잭션으로 대체하려고합니다. 그럼 어떻게해야합니까?

해결법

  1. ==============================

    1.EntityManagerFactory를 삽입 한 다음 EntityManager를 수동으로 생성 해보십시오.

    EntityManagerFactory를 삽입 한 다음 EntityManager를 수동으로 생성 해보십시오.

    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
    
    public boolean processBills() throws Exception{
    
       EntityManager em = entityManagerFactory.createEntityManager();
    
       EntityTransaction tx = null;
    
       Session session = null;
    
       try{
    
           session = em.unwrap(Session.class);
           tx = em.getTransaction();
    
  2. ==============================

    2.@PersistenceContext에 의해 반환 된 EntityManager 인스턴스는 항상 컨테이너로 관리되는 EntityManager입니다. 컨테이너 관리 EntityManager는 항상 JTA EntityManager이므로 컨테이너의 라이프 사이클을 관리합니다. 이제 getTransaction ()을 호출하는 것이 불법 인 이유에 대해 이해할 수 있습니다. 그러면 도움이 될 것입니다.

    @PersistenceContext에 의해 반환 된 EntityManager 인스턴스는 항상 컨테이너로 관리되는 EntityManager입니다. 컨테이너 관리 EntityManager는 항상 JTA EntityManager이므로 컨테이너의 라이프 사이클을 관리합니다. 이제 getTransaction ()을 호출하는 것이 불법 인 이유에 대해 이해할 수 있습니다. 그러면 도움이 될 것입니다.

  3. ==============================

    3.@ 트랜잭션 주석은 사용자가 필요로하는 것을 정확하게 수행합니다.

    @ 트랜잭션 주석은 사용자가 필요로하는 것을 정확하게 수행합니다.

    http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#transaction-declarative-annotations

  4. ==============================

    4.값이 true 인 hibernate.jta.allowTransactionAccess 속성을 추가하면 수동으로 사용할 수 있어야합니다. JTA가 관리하는 일부 코드를 수동으로 사용하는 전략을 혼합하는 것은 좋지 않습니다.

    값이 true 인 hibernate.jta.allowTransactionAccess 속성을 추가하면 수동으로 사용할 수 있어야합니다. JTA가 관리하는 일부 코드를 수동으로 사용하는 전략을 혼합하는 것은 좋지 않습니다.

  5. from https://stackoverflow.com/questions/42900265/how-to-start-a-transaction-in-jpa-using-entitymanager by cc-by-sa and MIT license