В мое приложение входит 2 транзакции, которые хотят обновить подмножество тех же объектов.Однако некоторые из этих сущностей отсутствуют в базе данных, поэтому оба потока создают одну и ту же сущность и пытаются ее зафиксировать.Вызов базы данных. Дублирующая запись для первичного ключа.Как мне справиться с этим?
например, Транзакция 1 хочет обновить сущности A, B, C, D, E, F Транзакция 2 хочет обновить сущности D, E, F, G, H, I Моя база данных толькоимеет записи для сущностей A, C, E, G и I
Так что транзакции 1 и 2 пытаются создать сущность D. В которой второй поток не может зафиксировать, поскольку D является первичным ключом и теперь уже существует.
Я пытался использовать pessimistic_write, но это не помогает записям, которые еще не существуют.
Я попытался обернуть мой вызов persist () в попытку catch, но похоже, чтоИсключение выдается внутренне в JPA, и мое приложение его никогда не видит.
Большинство поисков в Google возвращают примеры блокировки существующих записей, и если в них упоминаются одновременные вставки, это выходит за рамки статьи.
В некоторых статьях говорится, что я должен использовать уникальный идентификатор, сгенерированный базой данных, в моем случае это не работает.Или я должен использовать версию в моей сущности, но опять же моя модель сущности повышает ее точность на основе своих предыдущих значений, значения сущностей не изолированы, а полагаются на предыдущие транзакции.
Я думал опредварительно заполняет базу данных, но, вероятно, существует более миллиарда возможных действительных ключей сущностей, хотя я работаю только с набором из примерно 20 000 ключей, но я не знаю, что это такое, пока не произойдет транзакция.
Это мой персистентный код с упаковкой try catch, я никогда не вижу сообщения «INSERT Persistence collision», выходящего из моего приложения, только трассировка стека JPA.
if (cellmu == null)
{
CellMUEntity cellmuNew = new CellMUEntity();
cellmuNew.setId(cellOuter);
cellmuNew.setDistribution(mus);
try {
em.persist(cellmuNew);
} catch (Exception e) {
System.out.println("INSERT Persistence collision, " +e.getClass().getName() +" read and refine (" + cellOuter+")" );
cellmuNew = em.find(CellMUEntity.class,cellOuter,LockModeType.PESSIMISTIC_WRITE);
cellmuNew.setDistribution(cellmuNew.getDistribution().refine(mus));
em.merge(cellmuNew);
}
}
здесь есть часть трассировки стекаиз jpa ...
[2019-05-01T21:07:07.654+1000] [glassfish 4.1] [WARNING] [jts.unexpected_error_occurred_in_after_completion] [javax.enterprise.system.core.transaction.com.sun.jts.jta] [tid: _ThreadID=70 _ThreadName=p: thread-pool-1; w: 2] [timeMillis: 1556708827654] [levelValue: 900] [[
JTS5054: Unexpected error occurred in after completion
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.1.v20150605-31e8258): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '6ad63bd4' for key 'PRIMARY'
Error Code: 1062
Call: INSERT INTO mucell (cellid, mu_high, mu_low) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery((face=3, pos=ad63bd400000000, level=13):[0.0, 47499.492305012])
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)