Barcelona
Barcelona

Reputation: 2132

Deadlock when using Spring transaction

I have the following classes and methods as below:

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" />

I got exception org.hibernate.exception.LockAcquisitionException: ORA-00060: deadlock detected while waiting for resource! and in exception stacktrace this error happened at method checkEmployee.
Why is this error happenning when the default Propagation of Transaction is REQUIRED? Can anyone explain this?

Upvotes: 1

Views: 13103

Answers (1)

ssedano
ssedano

Reputation: 8432

With the data you provide is not enough. Try to remove the @Transactional("emp") from the class EmployeeService and place it at a method level. That would relieve the db to start unneeded transactions.

Try enabling debug log level for org.springframework.orm and see what is happenning.

Add to your question the whole chain, also add every call to Autowired services inside the checkEmployee.

Bear in mind that @Transactional only applies after passing thru a proxy and the method must be visible (no private methods). Your private method checkEmployee is not applying its @Transactional annotation, it is indeed inheriting from its caller. As long as its caller is public annotated with @Transactional and called from a proxy (eg autowired).

Another thing that can help is to set a breakpoint in the call to saveOrUpdate in saveEmployee and check how many transactions are in db. In mysql SHOW INNODB STATUS\G

The commit is issued when the top level method (the which started the most inner transaction) returns trhu a proxy. This applies for every transaction you start.

Upvotes: 2

Related Questions