Springboot synchronized method

10,984

Although, I'm still not convinced that you'll need synchronized in this case, you could extract a method that gets you the next value:

private synchronized long getNextVal(...){     
  return ultimoRegistro++;
}

I would suggest to use sequence generator (may be create a sequence table) provided by DB instead of the approach you are following. In your case: sequence-generator

Share:
10,984
Fabio Ebner
Author by

Fabio Ebner

Updated on June 04, 2022

Comments

  • Fabio Ebner
    Fabio Ebner almost 2 years

    I have one method that I need that be run synchronized (If 10 users call this method the first runs the method and the 9 remaining wait he finish, then the second executes the method ant the 8 remaining wait...)

    So this method need to save one register in my postgresql, but I need to begin and commit the transaction inside this method, so search on internet I found this solution:

    @org.springframework.transaction.annotation.Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW)
    private synchronized  Registro gerarRegistro(Protocolo protocolo, List<ServicoCalculado> servicos,String especialidade, LocalDateTime dtRegistro) throws Exception{
        Registro novoRegistro = new Registro();
        //this method executes one method in my service that call a method in my repository with this query -> @Query(value = "SELECT MAX(numero_registro) FROM rtdpj.registro WHERE tp_especialidade = ?1", nativeQuery = true)
        Long ultimoRegistro = this.registroService.findLastRegistro(especialidade);     
    
        ultimoRegistro++;
        novoRegistro.setEspecialidade(especialidade);
        novoRegistro.setNrPastaPj(protocolo.getPastaPJ());
        novoRegistro.setNumeroRegistro(ultimoRegistro);
        novoRegistro.setRegistro(registroService.gerarRegistro(ultimoRegistro, novoRegistro.getDataRegistro()));
        novoRegistro.setProtocolo(protocolo.getId());
        novoRegistro.setRegistroReferencia(protocolo.getRegistroReferencia());
        novoRegistro.setObjetos(protocolo.getObjetos());
        novoRegistro.setSituacaoAtual(protocolo.getSituacaoAtualRegistro());
        novoRegistro.setObservacao(protocolo.getObservacaoRegistro());
        novoRegistro.setServicos(servicos);
        novoRegistro.setProtocoloCancelamentoIndisponibilidade(protocolo.getProtocoloCancelamentoIndisponibilidade());
        novoRegistro.setProtocoloIndisponibilidade(protocolo.getProtocoloIndisponibilidade());
        novoRegistro.setNatureza(protocolo.getNatureza());
        novoRegistro.setCliente(protocolo.getCliente());
        novoRegistro.setIcGuardaConservacao(protocolo.getIcGuardaConservacao());
        novoRegistro.setIcPossuiSigiloLegal(protocolo.getIcPossuiSigiloLegal());
        novoRegistro.setNumeroRegistroReferencia(protocolo.getNumeroRegistroReferencia());
    
    
    
        return this.registroService.save(novoRegistro);
    
    }
    

    It's the best way to does this? or have a better way?

    In my domain the propertie novoRegistro.setNumeroRegistro must be sequential withou jumps, so If I use SERIAL and at the moment that saves the register something happend I will lost the nextval, and I have to keep the client's arrival order FIRST to IN is the FIRST to get a number

    • cosmos
      cosmos over 5 years
      Why would you need it to be synchronized in the first place?
    • zapl
      zapl over 5 years
      Don't require synchronization. What if you have 2 servers? What you seem to do is to manually increment ids, for that you have autogenerated / incremented ids by the database. (stackoverflow.com/questions/787722/postgresql-autoincrement ?)
    • Fabio Ebner
      Fabio Ebner over 5 years
      @cosmos I edit the question :D tks
    • Ian Lim
      Ian Lim over 5 years
      You can try AtomicLong and see if it works for you.
  • Fabio Ebner
    Fabio Ebner over 5 years
    but my problem are the transaction, only to put the "synchronized" dosen't works because the transaction is only commited when the execution of main method are finished (when I finish the first method that my user call, in my case when the controller returns the request) and if 3 users make a request, at same time I can't garanteer the call sequence but the execution sequence (if one request take more time than other he will catch the number first