Ответ 1
У меня есть автомобили → (1 -n) мест. И у меня есть внешний ключ в табличном месте (id_car). Этот внешний ключ не имеет индекса. Когда я добавляю индекс к этому внешнему ключу, моя проблема решена.
Обратитесь к этому ответу
У меня есть этот метод:
mymethod(long id){
Person p = DAO.findPerson(id);
Car car = new Car();
car.setPerson(p);
p.getCars().add(car);
DAO.saveOrUpdate(car);
DAO.saveOrUpdate(p);
DAO.delete(p.getCars().get(0));//A person have many cars
}
Сопоставление:
Person.hbm.xml
<!-- one-to-many : [1,1]-> [0,n] -->
<set name="car" table="cars" lazy="true" inverse="true">
<key column="id_doc" />
<one-to-many class="Car" />
</set>
<many-to-one name="officialCar"
class="Car"
column="officialcar_id" lazy="false"/>
Cars.hbm.xml
<many-to-one name="person" class="Person"
column="id_person" not-null="true" lazy="false"/>
Этот метод хорошо работает для одного потока и для нескольких потоков, дает мне ошибку:
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - WARN - org.hibernate.util.JDBCExceptionReporter - SQL Error: 60, SQLState: 61000
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.util.JDBCExceptionReporter - ORA-00060: deadlock detection while waiting for a resource
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - WARN - org.hibernate.util.JDBCExceptionReporter - SQL Error: 60, SQLState: 61000
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.util.JDBCExceptionReporter - ORA-00060: deadlock detection while waiting for a resource
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update
Операция АОП:
<tx:advice id="txAdviceNomService" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
<tx:method name="getAll*" read-only="true" propagation="SUPPORTS" />
<tx:method name="find*" read-only="true" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
NB: Когда я добавляю Thread.sleep(5000) после обновления, это нормально. Но это решение не чистое.
У меня есть автомобили → (1 -n) мест. И у меня есть внешний ключ в табличном месте (id_car). Этот внешний ключ не имеет индекса. Когда я добавляю индекс к этому внешнему ключу, моя проблема решена.
Обратитесь к этому ответу
Согласно вашему отображению последовательность операций должна выглядеть следующим образом:
Person p = DAO.findPerson(id);
Car car = new Car();
car.setPerson(p);
DAO.saveOrUpdate(car);
p.getCars().add(car);
Car firstCar = p.getCars().get(0);
firstCar.setPerson(null);
p.getCars().remove(firstCar);
if (p.officialCar.equals(firstCar)) {
p.officialCar = null;
p.officialCar.person = null;
}
DAO.delete(firstCar);
Обновление или удаление означает получение монопольной блокировки даже на уровне изоляции READ_COMMITTED.
Если другая транзакция хочет обновить ту же строку текущей запущенной транзакцией (которая уже заблокировала данную строку), вы не получите взаимоблокировку, а получите исключение тайм-аута для получения блокировки.
Поскольку вы получили тупик, это означает, что вы получаете блокировки для нескольких таблиц, и получение блокировок не организовано должным образом.
Поэтому убедитесь, что методы уровня обслуживания устанавливают границы транзакций, а не методы DAO. Я вижу, что вы объявили методы get и find для использования SUPPORTED, то есть они будут использовать транзакцию, только если она запущена. Я думаю, что вы должны использовать REQUIRED для них, но просто пометьте их как read-only = true
.
Поэтому убедитесь, что аспект транзакции применяет границу транзакции к "mymethod", а не к DAO.