Как читать сохраненный экземпляр в методе spring с помощью @Transactional - PullRequest
0 голосов
/ 03 марта 2020

Я использую аннотацию @Transactional для целей отката, я добавил в методы контроллера в своем приложении Spring-Boot, чтобы мои сохранения происходили только тогда, когда все происходило без ошибок, вот как я добавлена ​​аннотация:

    @PostMapping(value = "/add/people")
    @Transactional
    public ResponseEntity<?> addGroundToPerson(@RequestParam("ground") String newGround, @RequestParam("person") String person {
        try {
             personService.addPerson(person, ground);
             Ground addedGround = groundService.addGround(pnewGround);
        } catch (NoSuchElementException e) {
            return new ResponseEntity<>(new CustomErrorType(e.getMessage()), HttpStatus.NOT_IMPLEMENTED);
    }

addPersonToGround сохраняет этого человека в базе данных и с его адресом.

addGround сохраняет новое поле в базе данных с указанием этого человека, а само поле имеет address.

Метод My Service, который не работает:

public void registerAddress(HasAddress hasAddress) throws NoSuchElementException {

        Address address = hasAddress.getAddress());
        State state = address.getState();

        //here's where I'm getting the error
        State dbState = searchState(state); //stateRepository.getStateByName();

        address.setState(state);
        hasAddress.setAddress(address);

        addressRepository.save(address);
    }

RegisterAddress вызывается два раза, первый работает нормально, но, поскольку я сохранил в первый раз, второй один не работает (имейте в виду, что мой код намного больше, чем этот, и я не могу просто снять сохранение, и я попытался, поверьте мне).

Я пытался поместить @Transactional в слой службы, но он отправляет мне эту ошибку:

org.hibernate.TransientPropertyValueException: объект ссылается на несохраненный временный экземпляр

Он работает нормально, когда я просто сохраняю объекты, но не работает нормально, когда мне нужно получить объект после его сохранения. И это моя проблема. Лучший пример, который у меня есть, это:

  1. У меня есть адрес в каждом человеке, и в нем есть состояние.
  2. Я хочу повторно использовать состояние для каждого адреса, если он одинаковый.
  3. Я регистрирую человека, и он регистрирует новый адрес (иногда с использованием состояний, которые уже существуют в базе данных).
  4. Я пытаюсь зарегистрировать землю, и когда Я пытаюсь получить это состояние для его повторного использования. Я получаю сообщение об ошибке:

    вложенное исключение - org.hibernate.TransactionException: транзакция была помечена только для отката; не могу зафиксировать

Я думаю, что это происходит потому, что когда я «сохраняю» объект в первый раз, он не фиксируется, поэтому он остается временным, и я просто не могу получить временный объект. Я пытаюсь сделать все логи c и сохранить их в конце или выполнить откат, если произойдет какое-то исключение, но я получаю эту ошибку из-за аннотации.

1 Ответ

2 голосов
/ 03 марта 2020

Столько всего плохого в этом. Позвольте мне начать с того факта, что вы поместили @Transactional в слой Controller вместо слоя Service. Логос вашего метода c также должен быть на уровне сервиса. Это - rollbackFor = Exception.class на самом деле не нужно, потому что Spring по умолчанию ставит rollbackFor = { RuntimeException.class, Error.class } на все методы, помеченные @Transactional. И теперь причина, по которой вы получаете упомянутое исключение, заключается в том, что вы поместили туда блок try / catch. Транзакции Spring помечаются как откатные, только когда выбрасывается исключение независимо от того, было ли оно перехвачено . Вы должны либо удалить try / catch, либо найти способ сделать это вне транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...