2014-05-13 1 views
1

에서 다른 @Transactional 방법에서 하나 개의 서비스에서 @Transactional 메소드를 호출하는 방법 내가 가진 :다른 서비스

1) 서비스 :

@Service("scanner") 
@Transactional 
public class Scanner 
{ 
    @Inject 
    AnalyzerService analyzerService; 

    @Transactional 
    private void scan() { 
     analyzerService.analyze(); 
    } 
} 

2) 서비스 :

@Service 
public class AnalyzerService 
{ 
    @Inject 
    AnalyzerDao analyzerDao; 

    @Transactional 
    public void analyze() { 
     List<AnalyzerResult> items; 
     // code filling items list removed; 
     save(items); 
    } 

    @Transactional 
    private void save(List<SomeType> items) { 
     analyzerDao.save(items); // <--- Why after call save items are not saved in DB? 
    } 
} 

3) Dao :

@Repository 
public class AnalyzerDao extends GenericDaoImpl<AnalyzerResult> 
{ 
    //all needed methods for find, edit, delete and save which works fine in other cases. 
} 

질문 :

analzyerDao.save(items) DB가 여전히 비어있는 이유는 무엇입니까? 트랜잭션에 문제가 있습니까? 내가 DB하지만 예외가 나타나는 라인 analyzerDao.save(items) 다음 기록을 던져 직후 flush() 방법 getSession().getTransaction().commit()를 호출하면 는 :

Caused by: org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:660) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at com.sun.proxy.$Proxy44.execute(Unknown Source) 
    at org.quartz.core.JobRunShell.run(JobRunShell.java:223) 
    ... 1 more 
Caused by: org.hibernate.TransactionException: Transaction not successfully started 
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:127) 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) 
    ... 9 more 

어떻게

은 구현 방법의 벌금을 '저장'을 작업을 수행해야 하는가? 첫 번째 트랜잭션이 완료된 후에뿐만 아니라, line analyzerDao.save (items)에 항목을 저장하려면 어떻게해야합니까?

답변

1

필요한 것은 저장해야하는 것을 저장하기위한 새로운 거래입니다. 이것을 @Transactional 주석으로 구성하여 REQUIRES_NEW으로 설정하면됩니다. 당신이 this 컨텍스트 내에서 메소드를 호출하기 때문에

불행하게도 귀하의 경우는 save(items);을 수행 할 때,이 때문에 당신은 필드 보류에 서비스를 주입 할 수있을 트랜잭션 인터셉터는 호출을 가로 챌 의미, 조금 까다 롭습니다

@Service 
public class DefaultAnalyzerService implements AnalyzerService { 
    @Inject 
    AnalyzerDao analyzerDao; 
    @Inject 
    AnalyzerService analyserService; 

    @Transactional 
    @Override 
    public void analyze() { 
     List<AnalyzerResult> items; 
     // code filling items list removed; 
     analyserService.save(items); 
    } 

    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    @Override 
    public void save(List<SomeType> items) { 
     analyzerDao.save(items); // <--- Why after call save items are not saved in DB? 
    } 

} 
, 즉 save(List<SomeType> items)의 가시성이었다 변경 또 다른 일이

: 자체 트랜잭션 인터셉터에 의해 차단 될 메소드의 호출을 강요하는 대신이의 주입 서비스에 호출, 다음의 구현을 시도하십시오 이제는 트랜잭션 인터셉터에 의해 가로 챌 수있는 공개 된 인터페이스가 추출되었습니다. 이것은 스프링의 한계로 인해 필요하지만 AspectJ를 사용하여 인터셉터를 처리 할 수 ​​있으므로 here을 살펴 보시기 바랍니다.

+0

감사합니다. REQUIRES_NEW가 도움을주었습니다. :) – Roman

1

데이터가 트랜잭션이 커밋 될 때까지 데이터베이스에 나타나지 않습니다. @Transactional 메소드의 경우,이 메소드에서 리턴 된 후 스프링 에 의해 트랜잭션이 커밋됩니다.

개인 방식의 @Transactional은 효과가 없으므로 Scanner.scan()은 전혀 트랜잭션이 아닙니다.