1
resposta

Login com Herança

Bom dia, estou fazendo o Curso Spring MVCII

E estou tentando aplicar herança no meu usuário.

Criei 2 classes Funcionario e Medico que herdam de Usuario.

Porém no meu DAO de Usuario quando o metodo loadUserByUsername é chamado, pelo log o Hibernate não traz as Roles, fiz varias tentativas diferentes para tentar logar, e a unica forma que consegui foi fazendo a query se toranr um Funcionario.class ao invés de um Usuario. class. Porém eu excluo o Medico no login. Percebi que quando implemento Herança a classe pai não é mais instanciada e por tanto não consigo usar da mesma forma.

Minha duvida é se existe alguma forma de buscar usuário depois de implementar herança.

Classe Usuario

@Entity
@Table(name = "t_gvet_usuario")
@Inheritance(strategy = InheritanceType.JOINED)
@Scope(value = WebApplicationContext.SCOPE_REQUEST )
public class Usuario implements UserDetails, Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="id_usuario")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idUsuario;

    @Column(name="nome_usuario")
    @NotNull
    private String nome;

    @Column(name="sobrenome_usuario")
    private String sobrenome;

    @Column(name="data_nascimento_usuario")
    private Calendar dataNascimento;

    @Column(name="sexo_usuario")
    private Sexo sexo;

    @Column(name="cpf_usuario")
    @NotNull
    private String cpf;

    @Column(name="login_usuario")
    @NotNull
    private String login;

    @Column(name="senha_usuario")
    @NotNull
    private String senha;

    @Column(name="permissao_usuario")
    @OneToMany(fetch = FetchType.EAGER)
    private List<Role> permissao = new ArrayList<Role>(); 

    @Column(name="data_criacao")
    private Calendar dataCriacao;

    @Column(name="email_usuario")
    private String email;

    @Column(name="tel_usuario")
    private String telefone;

    @Column(name="tipo_usuario")
    private TipoUsuario tipo;

    @Column(name="cel_usuario")
    @NotNull
    private String celular;

    @Column(name="salario_usuario")
    private BigDecimal salario;


    public Usuario() {
        super();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.permissao;
    }

    @Override
    public String getPassword() {
        return    this.senha; 
    }

    @Override
    public String getUsername() {
        return this.login;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
// getters and setters

Classe Medico

@Entity
@PrimaryKeyJoinColumn(name="id_usuario")
@Table(name = "T_GVET_MEDICO")
@Scope(value = WebApplicationContext.SCOPE_REQUEST )
public class Medico extends Usuario {

    private static final long serialVersionUID = 1L;

    @Column(name="crmv_medico")
    private String crmv;

    @Column(name="cnpj_empresa_medico")
    private String cnpj;
    //contrutor cheio vazio e get/set
    }
}

Classe Funcionario está igual a médico porém com Pis e carteira de trabalho ao invés de crmv e cnpj

Classe DAO

@Repository
public class UsuarioDAOImpl extends GenericDAOImpl<Usuario, Integer> implements UsuarioDAO, UserDetailsService{
    @Override
    public Usuario loadUserByUsername(String login) {

            Query q = em.createNativeQuery("select * from t_gvet_usuario US " + 
                    "left join t_gvet_usuario_role RL on RL.t_gvet_usuario_id_usuario = US.id_usuario "+
                    "where US.login_usuario = '" + login + "';", Usuario.class);

            Usuario user = (Usuario) q.getSingleResult();

            if(user != null) {
                if(user.getTipo() != TipoUsuario.MEDICO) {
                    user = (Medico) em.createNativeQuery("select * from t_gvet_usuario US "
                            + "left join t_gvet_medico ME on US.id_usuario = ME.id_usuario "
                            + "where US.login_usuario like '" + login + "';",Medico.class); 
                }else {
                    user = (Funcionario) em.createNativeQuery("select * from t_gvet_usuario US "
                            + "left join t_gvet_funcionario FN on US.id_usuario = FN.id_usuario "
                            + "where US.login_usuario like '" + login + "';",Funcionario.class);
                }
                String loginUsuario = user.getLogin();
                if(loginUsuario.equals(login)) {
                    return user;
                }
            }
        throw new UsernameNotFoundException("Usuário" + login + " não foi encontrado");
    }
}
1 resposta

Olá Victor, tudo bem? Peço desculpas pela demora no retorno! Bem, particularmente nunca tentei implementar o Login com diversos tipos usuários e cada tipo herdando de uma Classe usuário, mas penso que como você está usando essa herança, então no banco de dados vão ser criadas duas tabelas no caso médico e funcionário, correto? Então penso sobre ser a melhor abordagem, talvez criar um campo para identificar cada um não fosse melhor? Particularmente acho que você está trabalhando como se a classe pai fosse na verdade uma interface e os filhos tivessem implementando essa interface e ai sim tudo isso seria possível, porém não é esse o caso. E herança é um conceito muito complexo de utilizar e por isso temos esses problemas, algumas problemas são apresentados no curso de SOLID com Java: Orientação a Objetos com Java, acho que você poderia dar uma olhada nesse curso e pensar se é realmente a melhor alternativa usar herança nesse cenário.

Espero ter ajudado!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software