Olá amigo. DTOs são classes para transferir dados entre camadas da sua aplicação. Você sempre verá as perguntas sendo respondidas com "Depende" e "Varia o contexto". E é verdade. Programar envolve saber o que usar, quando e onde. Vou tentar responder de acordo com a minha experiência de desenvolvimento.
- Sendo sincero, costumo usar DTOs geralmente na camada de borda (Controllers, Chamadas de APIs, Mensageria, etc). Como java trabalha com referência de memória, você pode passar o objeto completo entre as camadas de sua aplicação. Claro que isso não é regra, vou invocar o varia o contexto.
- Isso geralmente vai de acordo com a arquitetura do seu projeto e gostos pessoais... Gosto de trabalhar com uma arquitetura hexagonal, onde cada camada do sistema é separada. Minhas classes de domínio possuem apenas o básico POJO de uma entidade. Toda manipulação é feita em uma camada de serviço, então neste caso o meu toDTO ou fromDTO fica na camada de serviço. O pessoal mais centrado no encapsulamento forte costuma deixar esse método dentro da classe do próprio objeto, ou como método ou recebendo o DTO num construtor.
- O que é que você quer fazer? Neste caso, eu tenho dois DTOs (ou records), um específico para as credenciais e um outro específico para updates nos dados do usuário. Cada um utilizado no seu contexto. O fluxo que atualiza os dados do usuário não envolve a atualização da senha, e vice versa. DTOs podem (e geralmente devem) ser criados para o objetivo específico dos dados que ele irá transportar. Você pode talvez estudar se uma aplicação de Patch não seja mais viável para você, ao invés de um PUT com a entidade completa. Isso também depende do seu conhecimento HTTP.
- Não, DTO nada mais é que um carregador, transportador de informações. Classes de domínios não são (nem podem ser) fundamentalmente DTOs. Seus relacionamentos serão sempre entre uma entidade e outra. Sua preocupação em relação a senha deve ser a criptografia do conteúdo dela, para que ela não seja salva no banco. Ou, você pode usar uma estratégia de carregamento Lazy nos campos que você não quer recuperar a primeira instância, caso esteja usando um ORM e recuperando a entidade toda. Ou ainda, você pode usar uma projection do spring data (um exemplo) para recuperar apenas o que aquela rota precisa do banco e mapear para um DTO (ou record), nada mais, nada menos. Isso excluiria a senha já na camada de persistência, nem do banco ela viria. Para exemplo, você pode criar um DTO que disponibilize numa rota GET apenas os dados do cliente necessários para a visualização, o que não incluiria a senha.
DTOs (e records) são uma mão na roda. Um exemplo disso é que você pode querer uma rota de paginação ou uma rota para buscar todos os registros de uma entidade para uma listagem em uma tabela, mas a sua tabela não vai ter todos os dados de toda a entidade numa linha. Isso fica para a visualização completa do item que você está tratando. Você pode ter uma rota só pra listar o básico na tabela (id, nome, cpf) e o botão de editar vai chamar a rota com o id, e nela você visualiza todos os dados do cliente que não foram trazidos para a tabela. Com isso você otimiza sua consulta no banco de dados, tráfego de rede e processamento.
Há muito que se possa fazer com DTO (e records). Vê como citei records várias vezes? rsrs. É uma implementação mais limpa do que o DTO, mas para dados de entrada, ainda se limita a não permitir Bean Validation, teria que fazer a validação numa função dedicada. Espero ter contribuido com sua dúvida.