2017-01-25 3 views
0

최근 Jboss 어플리케이션에 Spring을 통합했습니다. 또한 Spring 서비스 클래스 중 일부를 사용하는 독립 실행 형 응용 프로그램을 함께 작성합니다.Spring Standalone이 @Transactional을 인식하지 못합니다.

다음
@Component 
public class StandaloneTest { 

public static ApplicationContext context; 

public static void main(String[] args) { 
    context = new AnnotationConfigApplicationContext(StandaloneSpringBeanConfiguration.class); 
    StandaloneTest test = context.getBean(StandaloneTest.class); 
    System.out.println(context); 
    test.startProcess(); 
} 

public StandaloneTest() { 

} 

/** 
* Start the main process 
*/ 
private void startProcess() { 
     run(); 
} 

private void run() { 
    TestService testService = context.getBean(TestService.class); 
    testService.transactionalTest(); 
    System.out.println("finished"); 
} 

이 TestService의 소스입니다 : : 내 JBoss 서버에이 방법을 실행하면 예상대로

@Service 
public class TestServiceImpl implements TestService { 

public GeneralDAO generalDAO; 

private EntityManager em; 

private EntityManagerFactory emf; 

public TestServiceImpl(){} 

    @Transactional 
public void transactionalTest() { 
    Something something = new Something(); 
    getEntityManager().persist(something); 
} 

    public EntityManager getEntityManager() { 
    if (em == null) { 
     emf = Persistence.createEntityManagerFactory("xxx"); 
     em = emf.createEntityManager(); 
    } 
    return em; 
} 


} 

이는 @Transactional 주석이 작동 여기 내 독립 소스입니다. 그러나 독립 실행 형 응용 프로그램을 실행하면 @Transactional 주석이 무시 된 것 같습니다. 나는 이유를 알 수 없다.

누구나 내가이 일을하기 위해해야 ​​할 일이 있거나 아이디어/의견이 있으면 누구나 공유하십시오. 감사!

@Configuration 
@ComponentScan 
@EnableTransactionManagement 
public class StandaloneSpringBeanConfiguration { 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setPersistenceUnitName("myPersistenceContext"); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan(new String[] { "xxx.xxx.xxx"}); 

     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
    // em.setJpaProperties(additionalProperties()); 

     return em; 
    } 

    @Bean 
    public DataSource dataSource(){ 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
     dataSource.setUrl("jdbc:mysql://localhost:3306/jboss_test"); 
     dataSource.setUsername("root"); 
     dataSource.setPassword("root"); 
     return dataSource; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
      JpaTransactionManager transactionManager = new JpaTransactionManager(emf); 
      transactionManager.setEntityManagerFactory(emf); 
      return transactionManager; 
    } 


    @Bean 
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ 
     return new PersistenceExceptionTranslationPostProcessor(); 
    } 

더 많은 업데이트

@Service 
public class TestServiceImpl implements TestService { 

public GeneralDAO generalDAO; 

@PersistenceContext 
private EntityManager em; 

private EntityManagerFactory emf; 

public TestServiceImpl(){} 

@Transactional 
public void transactionalTest() { 
Something something = new Something(); 
em.persist(something); 
} 

} 

이 확실히 올바른 방향으로 날 이동 :

업데이트

여기에 내 구성 파일입니다. 지금이 오류가 발생합니다. JTA UserTransaction을 사용할 수 없습니다. 'userTransaction'또는 'userTransactionName'또는 'transactionManager'또는 'transactionManagerName'을 지정하십시오.

문제를 해결하는 데 문제가 있습니다. transactionManager의? 내가 JOTM 또는 Atomikos를 독립 실행 형으로 사용해야하는 곳을 읽고 있었지만 JOTM을 Spring 4에서 사용할 수 있다고 생각하지 않습니다. Atomikos는 나를위한 옵션이 아닌 Maven을 사용해야합니다. JTATransactionManager를 사용하면 동일한 결과를 얻을 수 있습니다.

작업 솔루션

JTA 설명서 오류가 오늘 아침에 그 자체를 해결하는 것 같았다. 무슨 일이 일어 났는지 모르겠다. 내가 그때는 IllegalArgumentException 알 수없는 엔티티

구성

public class StandaloneSpringBeanConfiguration { 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan(new String[] { "xxx.xxx.xxx", "xxx.xxx.xxx"}); 

     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
    // em.setJpaProperties(additionalProperties()); 

     return em; 
    } 

    @Bean 
    public DataSource dataSource(){ 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setDriverClassName("com.mysql.jdbc.Driver"); 
     dataSource.setUrl("jdbc:mysql://localhost:3306/jboss_test"); 
     dataSource.setUsername("root"); 
     dataSource.setPassword("root"); 
     return dataSource; 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); 
     return transactionManager; 
    } 


    @Bean 
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ 
     return new PersistenceExceptionTranslationPostProcessor(); 
    } 
을 받고 있었기 때문에 필요한 모든 패키지가 LocalContainerEntityManagerFactoryBean에 의해 스캔 된 것을 확인했다

서비스 클래스

+0

Spring에 대해 어떤 트랜잭션 관리자를 구성 했습니까? – dunni

+0

위의 구성 파일을 추가했습니다. - 죄송합니다. shoulda가 먼저이 파일을 게시했습니다. 지금은 JpaTransactionManager를 사용하고 있습니다.내 jboss에서 jtaTransactionManager를 사용하고 있습니다. –

+0

물론 그건 무시됩니다. 당신은'EntityManagerFactory'를 설정 중이고 그것을 사용하지 않습니다. 기본적으로 전체 구성은 쓸모가 없습니다. 'getEntityManager()'메소드를 제거하고'@ PersistenceContext'를'private EntityManager' 필드에 넣으십시오. 첫 번째 장소에서'EntityManager'를 얻는 방법입니다. 당신의 코드는 트랜잭션 바인딩 된 것이 아닌'EntityManager' 만 얻으면 위험합니다. –

답변

1

거래는 잘 작동하는

@Service 
public class TestServiceImpl implements TestService { 

public GeneralDAO generalDAO; 

@PersistenceContext 
private EntityManager em; 

private EntityManagerFactory emf; 

public TestServiceImpl(){} 

@Transactional 
public void transactionalTest() { 
Something something = new Something(); 
em.persist(something); 
} 

} 
, 그들은 단순히 당신의 설정에서 작동하지 않습니다. 이는 다시 생성한다는 사실로 인해 트랜잭션 바운드 EntityManager으로 작업하기 때문입니다.

기본적으로 TestServiceImpl의 코드에 결함이 있습니다. getEntityManager() 메소드를 제거하고 EntityManager 필드에 @PersistenceContext으로 주석을 추가해야합니다.

@Service 
public class TestServiceImpl implements TestService { 

    public GeneralDAO generalDAO; 

    @PersistenceContext 
    private EntityManager em; 

    public TestServiceImpl(){} 

    @Transactional 
    public void transactionalTest() { 
     Something something = new Something(); 
     em.persist(something); 
    } 
} 

그게 전부입니다.

+0

맞습니다. 여기에 그 이유가 나와 있습니다. 'Transactional'은 Container Managed EntityManager *에서만 작동합니다. 즉, @ PersistenceContext를 사용하여 Spring (또는 JavaEE)에 의해 주입 된 EntityManager *를 의미합니다. 만약 당신이 * EntityManagerFactory.createEntityManager()를 호출하여 그것을 생성하는 것을 의미하는 * Application Managed EntityManager *를 가지고 있다면, 당신의 코드는 트랜잭션을 관리하고,'EntityManager.getTransaction(). begin()'과' EntityManager.getTransaction(). commit()' –

+0

팁 주셔서 감사합니다. 후속 질문에 위의 업데이트를 게시했습니다. 사이드 노트 - Klaus, 나는 실제로 트랜잭션을 명시 적으로 시작하거나 커밋하지 않고 과거에 EntityManagerFactory.createEntityManager를 사용할 수있었습니다. 방금 주석을 사용했습니다. –