Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

De quem é a responsabilidade por gerar o ID?

Nessa aula foi demonstrado o uso do UUID, sendo a própria classe de Domínio responsável por gerá-lo.

UUID tem diversos problemas e não se encaixa bem em muitas situações. É comum delegar ao Banco de Dados a geração do ID, entretanto isso não é feito na construção do objeto, mas no momento de persisti-lo.

Como ficaria o código para usar o ID gerado pelo Banco de Dados?

3 respostas

Olá Reinaldo! Tudo bem?

Isso é uma prática comum, especialmente quando queremos garantir que o ID é gerado no momento da persistência, e não durante a construção do objeto.

Para permitir que o banco de dados gere o ID, você pode seguir um caminho em que o ID é atribuído após a persistência. Aqui está um exemplo simplificado de como isso pode ser feito:

  1. Defina a entidade sem o ID no construtor: Inicialmente, ao criar a entidade, você não define o ID. Ele será nulo até que a entidade seja persistida.

    public class Evento {
        private Long id; // Supondo que o ID gerado pelo banco é do tipo Long
        private Categoria categoria;
        private String descricao;
        private LocalDateTime data;
        private Endereco endereco;
        private List<TipoIngresso> tipoIngressos = new ArrayList<>();
    
        public Evento(Categoria categoria, String descricao, LocalDateTime data, Endereco endereco) {
            this.categoria = categoria;
            this.descricao = descricao;
            this.data = data;
            this.endereco = endereco;
        }
    
        // Getters e setters omitidos
    }
    
  2. Configure o mapeamento para o banco de dados: Se estiver usando um ORM como o Hibernate, você pode configurar a geração automática do ID no banco de dados. Por exemplo, usando anotações JPA:

    @Entity
    public class Evento {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY) // Ou outra estratégia suportada pelo seu banco
        private Long id;
    
        // Resto da classe
    }
    
  3. Persistir a entidade: Quando você salva a entidade no banco, o ID é gerado e atribuído automaticamente.

    Evento evento = new Evento(categoria, descricao, data, endereco);
    eventoRepository.save(evento); // Após esse ponto, evento.getId() deve retornar o ID gerado pelo banco
    

Ao seguir esse caminho, você deixa a responsabilidade de gerar o ID para o banco de dados, o que pode ser vantajoso em termos de consistência e integridade dos dados, especialmente em sistemas distribuídos.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Mas com essa solução você altera o comportamento da Entidade.

Com o UUID, não existe Entidade criada sem uma identidade. Isso jamais acontecerá. Com o Banco de Dados da forma como foi implementado, a Entidade nascerá sem identidade, para em algum momento futuro essa informação ser preenchida.

Sem contar que você está usando um recurso do JPA que tem acesso aos atributos internos da Entidade, mas se você usar JDBC, por exemplo, você teria que expor um método para setar o ID após persistir.

Isso que você fez de setar posteriormente funciona, mas altera o comportamento, pois você pode ter uma Entidade "passeando" por aí sem identidade até ser preenchida, ou talvez tenha que expor um setter para o ID, que não seria desejado.

Estive pensando mas ainda não tenho uma proposta de solução.

Uma forma possível, talvez, seria o Repositório fornecer essa funcionalidade nextId(), e a aplicação quando criar o objeto, passa o ID. Se não quisesse estar vinculado ao Repositório, poderia ser um DomainService.

solução!

Oi, Reinaldo!

Sobre sua última dúvida: como criar entidades com identidade desde o início, mesmo quando o ID vem do banco de dados — uma ótima reflexão, e sim, isso impacta diretamente o comportamento da Entidade.

A solução que você propôs é bem alinhada com os princípios do DDD: o Repositório ou um Domain Service pode sim ser responsável por gerar e fornecer o ID antes da criação da Entidade. Isso garante que o objeto já nasça com identidade, sem depender da persistência.

Veja este exemplo usando um serviço GeradorDeId que o Repositório poderia usar ou expor:


public interface GeradorDeId {
    Long nextId();
}

Implementação simulada (poderia ser via sequence ou consulta ao banco):


public class GeradorDeIdBanco implements GeradorDeId {
    private final JdbcTemplate jdbcTemplate;

    public GeradorDeIdBanco(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public Long nextId() {
        return jdbcTemplate.queryForObject("SELECT nextval('evento_seq')", Long.class);
    }
}

No código de criação da entidade:


Long id = geradorDeId.nextId();
Evento evento = new Evento(id, categoria, descricao, data, endereco);

E sua entidade permanece com a identidade imutável desde o início:


public class Evento {
    private final Long id;
    private final Categoria categoria;
    private final String descricao;
    private final LocalDateTime data;
    private final Endereco endereco;

    public Evento(Long id, Categoria categoria, String descricao, LocalDateTime data, Endereco endereco) {
        this.id = id;
        this.categoria = categoria;
        this.descricao = descricao;
        this.data = data;
        this.endereco = endereco;
    }

    public Long getId() {
        return id;
    }

    // Getters omitidos
}

Importante: dessa forma, você respeita o princípio de que toda Entidade deve ter identidade desde sua criação, mesmo sem depender do JPA.

Fico à disposição.