2014-03-13 2 views
1

JPA에서 트랜잭션이 무엇인지 이해하려고합니다. 내가 MySQL 서버에 요청을 sniffering 코드를 디버깅하기 위해 노력하고있어JPA에서 트랜잭션 실현

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="survex" transaction-type="JTA"> 
    <jta-data-source>jdbc/MyDatabase</jta-data-source> 
    <exclude-unlisted-classes>false</exclude-unlisted-classes> 
    <properties> 
    </properties> 
    </persistence-unit> 
</persistence> 

:

내가 지속성과 글래스 피시에 배포 된 응용 프로그램이 있다고 가정 해

public String create() { 

     EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("survex"); 
     EntityManager em = entityManagerFactory.createEntityManager(); 
     Log log = em.find(Log.class, 1); 

     EntityTransaction transaction = em.getTransaction(); 
     transaction.begin(); // NOTING HAPPENS ... 
     log.setMessage("xxx"); 
     em.flush(); // OH, HERE IT IS -> SET autocommit=0; UPDATE LOG SET message = 'xxx' WHERE (id = 1) 
     log.setMessage("aaa"); 
     em.flush(); // OK -> UPDATE LOG SET message = 'aaa' WHERE (id = 1) 
     transaction.commit(); // NOTHING HAPPENS! WHERE IS COMMIT?! 

     log = em.find(Log.class, 1); 

     transaction = em.getTransaction(); 
     transaction.begin(); // STILL NOTHING ... 
     log.setMessage("555"); 
     em.flush(); // UPDATE LOG SET message = '555' WHERE (id = 1) 
     log.setMessage("666"); 
     em.flush(); // UPDATE LOG SET message = '666' WHERE (id = 1) 
     transaction.commit(); // NOTHING!!! 

     return log.getMessage(); 
    } 
    // SOMEWHERE OUTSIDE: COMMIT; SET autocommit=1; 

왜?! JPA가 왜 이상하게 행동 하는가?

나는 모든 transaction.commit() 호출에 커밋을 기대합니까? 아니면 뭔가 오해하고 있습니다.

+1

.flush 후에 .commit이 필요하다고 생각하십시오. –

+1

아니요 .commit 후 .flush는 예외로 연결됩니다. – corvax

답변

1

코드에 문제가 하나 있습니다. PersistenceContext를 JTA로 정의했지만 RESOURCE_LOCAL 트랜잭션 API (예 : EntityManager.getTransaction())로 작업했습니다.

Java EE 환경 에서처럼 주입 된 인스턴스를 UserTransaction : @Resource private UserTransaction transaction;EntityManager으로 만들면됩니다. 또한 CMT (컨테이너 관리) 트랜잭션을 비활성화해야합니다. 그렇지 않으면 자동으로 열거 나 닫힙니다.

+0

당신이 옳다고 생각합니다! 왜냐하면이 예외가 발생합니다 : SynchronizationType을 사용하여 EntityManager를 생성 할 수 없습니다. PersistenceUnit이 자원 로컬 트랜잭션으로 구성 되었기 때문에 이것을 만들 수 없습니다 - entityManagerFactory.createEntityManager (SynchronizationType.SYNCHRONIZED); 올바른 사용법에 대한 코드 샘플을 제공 할 수 있습니까? – corvax

+1

물론 있습니다. 그러나 EntityManagers의 유형에 대한이 좋은 기사 http://piotrnowicki.com/2012/11/types-of-entitymanagers-application-managed-entitymanager/를 읽고 코드를 작성하는 방법을 스스로 결정할 것을 제안합니다. EJB를 읽지 않고 시험해보기를 원한다면, 서블릿이나 EJB에 EntityManager를 삽입하기 위해 google을 작성하십시오. –