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

Persistência de Interface?

Olá pessoal!

Nem consegui pensar corretamente no título desse tópico para a minha dúvida. É o seguinte:

Estou desenvolvendo uma aplicação web em JSF (Mojarra), cuja especificação para persistência no banco é JPA (Hibernate). Tenho uma classe chamada PROJETO, que possui um List da classe DESPESA (@OneToMany anotado - Um projeto para Muitas despesas). Até então tudo estava funcionando lindamente bem, mas me dei conta que teria que criar um novo tipo de DESPESA, que possui atributos diferentes.

Quero dizer, agora vai existir também um tipo de despesa chamado DespesaComPessoal (inerente a despesas com mão de obra, que terá atributos BigDecimal como salário bruto, BigDecimal salário líquido, entre outros) cujos atributos não são nada relacionados a classe despesa anteriormente utilizado.

Qual a melhor solução para esse caso? Continuo usando a Despesa normalmente na List de despesas da classe Projeto, e somente adiciono os atributos novos, e quando não usar alguns deles coloco como null? Acho "medonha" essa abordagem pensando em OO.

Outra forma que pensei, seria criar a nova classe DespesaComPessoal mesmo, e mais uma List do tipo , mas seria estranho ter duas Lists parecidas na classe projeto.

Pensando que estou utilizando o JSF, e que o cliente setaria qual tipo de despesa ele deve escolher, qual a melhor solução?

3 respostas

Boa tarde Felipe,

Se um tipo de Despesa_A tem suas próprias características e comportamentos e o outro tipo de Despesa_B também, e um Projeto vai ter despesas A ou despesas B, não vejo problema algum em ter duas coleções em Projeto.

Sendo assim, você sabe que enquanto a sua regra de negócio for: um Projeto tem apenas um tipo de despesa, você terá apenas uma das coleções populadas, e a outra nula, e se um dia sua regra evoluir e um projeto tiver despesas dos dois tipos, você já terá o atributo no Projeto, bastando utilizá-lo. Neste cenário o Hibernate vai te dar 2 tabelas, uma da despesa A e outra da B. Seus registros nestas tabelas referenciarão o registro da tabela Projeto.

Seria possível criar criar uma Herança, onde uma superclasse Despesas teria o mínimo em comum, e as subclasses teriam as especialidades que precisam, ai seu Projeto teria uma coleção do tipo da superclasse Despesa, e você teria os mapeamentos certinhos pra fazer. Neste cenário o Hibernate vai gerar 3 tabelas se utilizar o método TABLE_PER_CLASS, sendo uma da Superclasse onde os dados comuns sempre ficarão, e duas para as subclasses. Ai no banco você vai ter um registro de despesa específico em uma tabela Despesa_A, apontando para um registro pai na tabela Despesa, e este apontando para o registro na tabela Projeto. Isso soa mais como OO, mas será um verdadeiro pesadelo de desempenho. Tem também a abordagem SINGLE_TABLE, onde toda essa herança geraria um único "tabelão", mas o ruim disso é que se for um registro de Despesa_A, as colunas de Despesa_B ficam nulas, mais performático, porém deselegante. Concluindo, é bem desaconselhado sair usando herança, só em último caso mesmo, então lhe recomendo ir para a outra solução (já que existe outra solução sem usar herança), ou tentar pensar em outra coisa. A herança não é sua amiga neste caso, por mais sedutora que possa parecer.

O uso de composição e interfaces não lhe ajudará aqui, uma vez que o JPA não aceite no mapeamento algo diferente de uma classe. Isso se deve porque a especificação JPA visa transpor uma ponte entre dois paradigmas diferentes (Orientação a Objetos VS Modelo Entidade-Relacionamento), e no segundo paradigma não existe polimorfismo.

Espero ter ajudado. Abraços.

Realmente, a herança me seduziu bastante a princípio para utilizar como alternativa nesse caso hehehe. Agora sabendo que o Hibernate criará três tabelas... me desanima um pouco.

Com relação a regra de negócio, desculpe por não ter esclarecido completamente: um Projeto sempre terá uma lista de despesas do tipo DespesaComum, e, na maioria das vezes, também terá a lista de tipo DespesaComPessoal. O que queria fazer era separar esses tipos de despesas, já que existem atributos diferentes nessa última.

solução!

Entendi, então neste caso lhe recomendo a solução de ter as duas coleções em Projeto mesmo.

Não é perda alguma que nem sempre a segunda coleção terá elementos, é como seu negócio funciona. E fica muito melhor do que atacar com herança, sem sombra de dúvidas.

Abraço.