2
respostas

Boas práticas para exibição de listas com campos de entidades diferentes

Preciso exibir uma lista de pessoas com os campos Código, Nome, CPF/CNPJ, Nome do Município e UF.

<p:autoComplete id="pessoaAutoComplete" value="#{myBean.pessoa}" var="p"
                 itemLabel="#{p.nome}" itemValue="#{p}"
                 completeMethod="#{myBean.completePessoa}">
    <p:column styleClass="TexAlRight">
       <h:outputText value="#{p.empresa_codigo}"/>
    </p:column>
    <p:column>
       <h:outputText value="#{p.nome}"/>
    </p:column>
    <p:column styleClass="TexAlCenter">
       <h:outputText value="#{p.cnpjcpf}" />
    </p:column>
    <p:column>
       <h:outputText value="#{p.cidade_nome}" />
    </p:column>
    <p:column styleClass="TexAlCenter">
       <h:outputText value="#{p.uf_sigla}" />
    </p:column>
</p:autoComplete>

Mas em minha classe Pessoa, não possuo os campos CPF/CNPJ, Nome do Muncípio e UF.

Então criei uma classe PessoaDTO:

@Immutable
@Data
@EqualsAndHashCode(callSuper = false, of = {"id"})
public class PessoaDTO {
    private Integer id;
    private Integer empresa_codigo;
    private String cnpjcpf;
    private String nome;
    private String cidade_nome;
    private String uf_sigla;
}

Faço uma nativeQuery e utilizo ResultTransformer para carregar as informações.

Passo a ter uma lista seja em um autoComplete ou selectOneMenu do tipo PessoaDTO, mas na maioria dos lugares eu associo a seleção de um item na lista diretamente com uma propriedade do tipo Pessoa.

Qual seria uma boa prática para se resolver esta situação?

Ter um converter de PessoaDTO para Pessoa?

Não trabalhar com o DTO e utilizar alguma outra forma para exibir as informações?

Obrigado desde já.

2 respostas

cara primeiramente como esses campos cpf, municipio e uf interagem com a tabela pessoa? posta tua querie ai pra termos noção.

Eu normalmente tenho minha entidade pessoa que se relaciona com a entidade municipio que se relaciona com a entidade uf então vc pode "caminhar" pelos atributos ex: pessoa.municipio.nome pessoa.municipio.uf.sigla

fazendo os relacionamentos direitinho vc nem precisa de dto

Bom dia Ricardo.

Então no meu caso elas não interagem diretamente, na minha entidade Pessoa eu tenho apenas um Enum que define se a pessoa é Física, Jurídica ou Exterior.

Eu tenho a entidade PessoaJuridica e a entidade PessoaFisica, além da entidade Pessoa.

E a ligação por ser @OneToOne eu tomei como base a recomendação deste artigo:

https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

Ou seja na classe Pessoa eu não tenho nada referente a PessoaFisica ou Juridica, mas nelas eu tenho a ligação:

   @MapsId
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "id")
    private Pessoa pessoa;

Quanto preciso obter dados de PessoaFisica ou Juridica no Bean eu busco pela Pessoa carregada e o Enum na Pessoa serve apenas para evitar ficar executando queries desnecessárias.

Dei uma resumida aqui, mas está é a minha consulta:

String sql = "SELECT p.id, p.empresa_codigo, j.cnpj AS cnpjcpf, p.nome, c.nome AS cidade_nome, u.sigla AS uf_sigla " +
                "FROM pessoas p " +
                "LEFT JOIN pessoas_juridicas j ON j.id = p.id " +
                "LEFT JOIN pessoas_enderecos e ON e.pessoa_id = p.id AND e.principal = TRUE " +
                "LEFT JOIN cidades c ON c.id = e.cidade_id " +
                "LEFT JOIN ufs u ON c.uf_id = u.id " +
                "WHERE p.empresa_id = :" + AppController.PARAM_EMPRESA_ID;

return getEntityManager()
                .createNativeQuery(sql)
                .setParameter("q", q)
                .setParameter(AppController.PARAM_EMPRESA_ID, loginController.getEmpresa().getId())
                .unwrap(org.hibernate.SQLQuery.class)
                .setResultTransformer(Transformers.aliasToBean(PessoaDTO.class))
                .list();

Obrigado pela atenção