Reputation: 2132
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
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