De acordo com seu mapeamento, a sequência de operações deve ficar assim:
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);
Uma atualização ou excluir significa adquirir um cadeado exclusivo , mesmo em
READ_COMMITTED
nível de isolamento. Se outra transação quiser atualizar a mesma linha com a transação em execução atual (que já bloqueou esta linha em questão), você não obterá um impasse, mas um tempo limite de aquisição de bloqueio exceção.
Como você obteve um deadlock, isso significa que você adquiriu bloqueios em várias tabelas e as aquisições de bloqueio não foram ordenadas corretamente.
Portanto, certifique-se de que os métodos da camada de serviço definam os limites da transação, não os métodos DAO. Vejo que você declarou o get e encontre métodos para usar SUPPORTED, o que significa que eles usarão uma transação somente se uma estiver iniciada no momento. Eu acho que você deve usar REQUIRED para eles também, mas simplesmente marque-os como
read-only = true
. Portanto, certifique-se de que o aspecto da transação aplique o limite da transação no "mymethod" e não nos DAO.