1
resposta

Spring boot + spring data problemas com transação

Bom dia, tenho um projeto com spring boot no qual gostaria que um método fosse transacional, porém o mesmo não ocorre, como podemos ver no código abaixo primeiro é chamado emailSolicitacaoRepository.saveAndFlush(emailSolicitacao), feito isso logo abaixo this.salvarEmail(emailSolicitacao, solicitacaoDTO.getEmail()), porem essa ultima rotina chamada estoura uma exceção, mas o roolback do saveAndFlush não é executado.

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.persistence.EntityManager;
import org.apache.commons.lang.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


@Service
public class EmailSolicitacaoService {

    @Autowired
    private EmailSolicitacaoRepository emailSolicitacaoRepository;

    @Autowired
    private ModelMapper mapper;

    @Autowired
    private EmailService emailService;

    @Autowired
    private EmailAnexoService emailAnexoService;

    @Autowired
    private EmailCorpoService emailCorpoService;

    @Autowired
    private EmailRemetenteService emailRemetenteService;

    @Autowired
    private TokenAcessoRepository tokenAcessoRepository;

    @Autowired
    private ParametroSistemaService parametroSistemaService;

    @Transactional
    public EntidadeEmailSolicitacao salvarSolicitacaoEmail(RequestSolicitacaoEmailDTO solicitacaoDTO, String token) {

        try {

            EntidadeEmailSolicitacao emailSolicitacao = mapper.map(solicitacaoDTO.getIdentification(), EntidadeEmailSolicitacao.class);
            emailSolicitacao.setTipoEnvio(solicitacaoDTO.getTipoEnvio());
            emailSolicitacao.setStatusEnvio(StatusEnvioEnum.PENDENTE);

            emailSolicitacao.setQtdeEnvio(1L);
            emailSolicitacao.setQtdeTentativasEnvio(1L);

            emailSolicitacao.setToken(this.getTokenAcesso(token));
            emailSolicitacao = emailSolicitacaoRepository.saveAndFlush(emailSolicitacao);
            this.salvarEmail(emailSolicitacao, solicitacaoDTO.getEmail());
            this.salvarEmailAnexo(emailSolicitacao, solicitacaoDTO.getEmail().getBody().getAttachments());
            this.salvarEmailCorpo(emailSolicitacao, solicitacaoDTO.getEmail().getBody());
            this.salvarEmailRemetente(emailSolicitacao, solicitacaoDTO.getSenderAccount());

            return emailSolicitacao;
        } catch (Exception ex) {           
            throw new ObjectBadRequestException("Erro ao salvar a solicitação!");
        }

    }


    public EntidadeTokenAcesso getTokenAcesso(String token) {

        Optional<EntidadeTokenAcesso> tokenAcesso = this.tokenAcessoRepository.findByToken(token);

        if (!tokenAcesso.isPresent()) {
            throw new ObjectNotFoundException("Token de acesso não encontrado!");
        }

        return tokenAcesso.get();
    }

    public void salvarEmail(EntidadeEmailSolicitacao emailSolicitacao, RequestEmailDTO emailDTO) {
        this.emailService.salvarEmail(emailSolicitacao, emailDTO);
    }

    public void salvarEmailAnexo(EntidadeEmailSolicitacao emailSolicitacao, List<RequestEmailAttachmentsDTO> listaEmailAnexoDTO) {

        listaEmailAnexoDTO.forEach((anexo) -> {
            this.emailAnexoService.salvarEmailAnexo(emailSolicitacao, anexo);
        });
    }

    public void salvarEmailCorpo(EntidadeEmailSolicitacao emailSolicitacao, RequestEmailBodyDTO emailCorpoDTO) {
        this.emailCorpoService.salvarEmailCorpo(emailSolicitacao, emailCorpoDTO);
    }

    public void salvarEmailRemetente(EntidadeEmailSolicitacao emailSolicitacao, RequestSenderAccountDTO emailRequerenteDTO) {
        this.emailRemetenteService.salvarEmailRemetente(emailSolicitacao, emailRequerenteDTO);
    }

}

application.properties

spring.datasource.hikari.connection-timeout=20000
spring.datasource.hikari.minimum-idle=3
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.max-lifetime=1200000
spring.datasource.hikari.connection-test-query=SELECT 1

spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false

spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=false

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/teste
spring.datasource.username=teste
spring.datasource.password=teste
1 resposta

Oi Eduardo,

Talvez seja por conta do saveAndFlush que você está chamando EmailSolicitacaoRepository.

Altere para o método save, e também adicione o seguinte parâmetro na anotação @Transactional:

@Transactional(rollbackFor = ObjectBadRequestException.class)

Veja se resolve.