Java непроверенное исключение, брошенное лямбдой, не пойман - PullRequest
0 голосов
/ 15 июня 2019

У меня есть функция, которая принимает две лямбды в качестве параметров.Эти функции генерируют определенное непроверенное исключение, которое я хочу, чтобы функция перехватывала:

    /**
     *
     * @param insert function to insert the entity
     * @param fetch function to fetch the entity
     * @param <T> type of entity being inserted
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public <T> T getOrInsertWithUniqueConstraints(Supplier<Optional<T>> fetch, Supplier<T> insert) {
        try {
            Optional<T> entity = fetch.get();
            T insertedEntity = entity.orElseGet(insert);
            return insertedEntity;
        }
        catch (Exception e){
            //I expect/want the exception to be caught here, 
            //but this code is never called when debugging
            Optional<T> entityAlreadyInserted = fetch.get();
            return entityAlreadyInserted.get();
        }
    }

, которая вызывается в функции, принадлежащей другой транзакции:

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
...
try {
    Player persistedPlayer = insertOrGetUtil.getOrInsertWithUniqueConstraints(
        () -> playerRepository.findOne(newPlayer.getUsername()),
        //this lambda throws the unchecked DataIntegrityViolationException
        () -> playerRepository.save(newPlayer)
    );
}
catch (Exception e){
    //the exception is caught here for some reason...
}

Не понимаю ли я, как Java лямбда-выраженияРабота?Также стоит отметить, что код использует Spring * @Transactional и CrudRepository

1 Ответ

0 голосов
/ 15 июня 2019

Исключение действительно происходит во время фиксации транзакции, которое происходит после возврата метода. Чтобы обойти это, я использовал EntityManager#flush(), чтобы вызвать любые исключения, которые произойдут при фиксации, прежде чем метод вернется:

    @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
    public <T> T getOrInsertWithUniqueConstraints(Supplier<Optional<T>> fetch, Supplier<T> insert) {
        try {
            Optional<T> entity = fetch.get();
            T insertedEntity = entity.orElseGet(insert);
            entityManager.flush();
            return insertedEntity;
        }
        catch (PersistenceException e){
            DataAccessException dae = persistenceExceptionTranslator.translateExceptionIfPossible(e);
            if (dae instanceof DataIntegrityViolationException){
                Optional<T> entityAlreadyInserted = fetch.get();
                return entityAlreadyInserted.get();
            }
            else {
                throw e;
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...