Синхронизированный бросок блока DuplicateKeyException - PullRequest
0 голосов
/ 25 сентября 2018

Ниже мой класс под резьбовые пружинные исполнители.В зависимости от типа источника / услуги TAXP, TAXS, методы TAXT вызываются.Логика в том случае, если 'taxInfo.getGroupingId ()' уже присутствует в первичной налоговой таблице, не вставляйте, иначе вставьте первичную таблицу.Все записи вторичных и третичных таблиц вставляются.НАЛОГ, НАЛОГИ, НАЛОГ - темы, и они получают данные в любое время.может быть интервал в миллисекунды или в то же время данные будут отправлены, поэтому блоки синхронизируются.

Все 3 метода вызываются из 3 разных исполнителей потоков.

executor1.insertPrimaryTaxInfo(taxInfo);
executor2.insertSecTaxInfo(taxInfo);
executor3.insertTerTaxInfo(taxInfo);

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class TaxServiceImpl implements TaxService {
private static final Logger LOG = LogManager.getLogger(ScanServiceImpl.class);
// TAXP
@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = TaxServiceException.class)
    public void insertPrimaryTaxInfo(TaxInfo taxInfo) throws TaxServiceException {
        String taxId = null;
        try {

            synchronized (this) {
                taxId = taxMapper.checkExists(taxInfo.getGroupingId());             
                if (taxId == null) {
                    taxMapper.insertTaxInfo(taxInfo);   // primary tax table
                }
            }

            LOG.info("tax id --  " + taxId);
        } catch (Exception ex) {
            LOG.error("Error inserting txId for " + taxInfo.getGroupingId()
                    + ex);
            throw new TaxServiceException(ex);
        }
    }


// TAXS
@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = TaxServiceException.class)
    public void insertSecTaxInfo(TaxInfo taxInfo) throws TaxServiceException {
        String taxId = null;
        try {

            synchronized (this) {
                taxId = taxMapper.checkExists(taxInfo.getGroupingId());             
                if (taxId == null) {
                    taxMapper.insertTaxInfo(taxInfo);   // primary tax table
                }
            }
            taxMapper.insertIntoSecTable(taxInfo); // secondary tax table
            LOG.info("tax id --  " + taxId);
        } catch (Exception ex) {
            LOG.error("Error inserting txId for " + taxInfo.getGroupingId()
                    + ex);
            throw new TaxServiceException(ex);
        }
    }


// TAXT
@Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = TaxServiceException.class)
    public void insertTerTaxInfo(TaxInfo taxInfo) throws TaxServiceException {
        String taxId = null;
        try {

            synchronized (this) {
                taxId = taxMapper.checkExists(taxInfo.getGroupingId());             
                if (taxId == null) {
                    taxMapper.insertTaxInfo(taxInfo);   // primary tax table
                }
            }
            taxMapper.insertIntoSecTable(taxInfo);  // secondary tax table
            taxMapper.insertIntoTerTable(taxInfo);  // Tertiary tax table
            LOG.info("tax id --  " + taxId);
        } catch (Exception ex) {
            LOG.error("Error inserting txId for " + taxInfo.getGroupingId()
                    + ex);
            throw new TaxServiceException(ex);
        }
    }

}

Проблема заключается в том, что TAXP, TAXS, TAXT получают данные одновременно, и 3 вышеуказанных метода вызываются одновременно.С разницей в миллисекунды один из потоков вставляет в основную таблицу, а другой поток пытается сделать то же самое, но находит запись, уже существующую в таблице, и выбрасывает исключение дубликата ключа.

Получаю следующее исключение:

"com.data.exception.TaxServiceException: org.springframework.dao.DuplicateKeyException: 
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (TAXDB2.TAX_PK) violated

Причиной синхронизации блока является преодоление этого исключения.Что не так с приведенным выше кодом?

1 Ответ

0 голосов
/ 25 сентября 2018

Похоже, вы пытаетесь генерировать первичные ключи не на основе guid в своем приложении вместо того, чтобы позволить базе данных генерировать их и сталкиваться с конфликтами.

Безуспешно пытаться синхронизировать доступ к базе данных в вашем приложении.Вы должны позволить базе данных управлять параллелизмом через существующие механизмы.Для получения дополнительной информации см. ACID .Кроме того, очень полезно посмотреть текущий уровень изоляции вашей реализации базы данных и то, что он делает по сравнению с другими.Например, документы SQL Server Общие сведения об уровнях изоляции

...