2012-08-16 4 views
1

를 사용할 때 아래로 다음과 같은 클래스와 방법이 있습니다교착 상태 Spring 트랜잭션

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 
import org.springframework.transaction.annotation.Transactional; 

@Component 
@Transactional("emp") 
public class EmployeeService { 

} 

@Component 
public class HumanResourceManager { 

[...] 

@Autowired 
private EmployeeService employeeService; 

@Transactional("emp") 
public void checkEmployee(Employee emp) { 

[..] 

employeeService.saveEmployee(emp); 

[...] 

} 

My Spring config: 

<bean id="employeeDataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${employee.driverClassName}" /> 
     <property name="url" value="${employee.url}" /> 
     <property name="username" value="${employee.user}" /> 
     <property name="password" value="${employee.password}" /> 
    </bean> 

    <bean id="employeeSessionFactory" 
     class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="employeeDataSource" /> 
     <property name="packagesToScan" value="com.xyz.employee.model" /> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${employee.dialect}</prop> 
       <prop key="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop> 
       <prop key="hibernate.show.sql">true</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="employeeTransactionManager" 
     class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="employeeSessionFactory" /> 
     <qualifier value="emp" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="employeeTransactionManager" /> 

내가 예외 org.hibernate.exception.LockAcquisitionException: ORA-00060: deadlock detected while waiting for resource있어! 예외 스택 추적에서이 오류는 메서드 checkEmployee에서 발생했습니다.
기본 거래 전파가 필수 일 때이 오류가 발생하는 이유는 무엇입니까? 아무도 이것을 설명 할 수 있습니까?

답변

2

제공하신 데이터만으로는 충분하지 않습니다. 클래스 EmployeeService에서 @Transactional("emp")을 제거하고 메서드 수준에 배치합니다. 그러면 DB에서 불필요한 트랜잭션을 시작하지 않아도됩니다.

org.springframework.orm의 로그 레벨을 debug으로 설정하고 무슨 일이 일어나는지보십시오.

질문에 전체 Autowired 서비스에 대한 모든 전화를 checkEmployee 안에 추가하십시오.

@Transactionalproxy을 통과 한 후에 만 ​​적용되며 메서드는 표시되어야합니다 (private 메서드 없음). private method checkEmployee@Transactional 특수 효과가 적용되어 있지 않습니다. 실제로 발신자와 상속됩니다. 호출자가 @Transactional로 주석을 붙이고 프록시 (예 : autowired)에서 호출 된 public 인 한.

saveOrUpdate을 호출 할 때 중단 점을 saveEmployee에 설정하고 db에 몇 개의 트랜잭션이 있는지 확인할 수 있습니다. mysql에서 SHOW INNODB STATUS\G

최상위 레벨 메소드 (가장 안쪽 트랜잭션을 시작한 메소드)가 trhu 프록시를 리턴 할 때 커밋이 발행됩니다. 이는 귀하가 시작하는 모든 거래에 적용됩니다.

+0

작동하지 않습니다. 트랜잭션의 전파가 필요하다는 것은 해당 스레드에 대한 트랜잭션이 하나만 있음을 의미하지만 교착 상태가 발생하면 트랜잭션이 두 개 이상 생성되어 DB를 잠그고 커밋하려고 시도합니다. – Barcelona

+0

메서드가 공용이고 내 입력 오류입니다. – Barcelona

+0

Are 마지막 메서드에서 autowired 메서드에 대한 다른 호출? – ssedano