JPA desencoraja o uso de interfaces?

Olá pessoal.

Estou trabalhando em JEE. E Atualmente estou estudando JPA.
Pelo que percebi até o momento, o JPA não suporta o uso de interfaces (como um atributo persistente), em classes de entidade.

Por exemplo, desenvolvi uma interface:

public interface Transportavel { //metodos abstratos }
e suas classes concretas. Uma dessas classes concreta é “Mobilia”:

@Entity @Table(name="tb_mobilia") public class Mobilia implements Transportavel { //atributos e metodos }
Para cada classe concreta eu tenho uma tabela mapeada no banco de dados.
Porém, eu nao sei como posso utilizar a interface “Transportavel” como um atributo persistente de uma classe de entidade.

Veja o exemplo:

[code]@Entity
@Table(name=“tb_conteiner”)
public class Container {
@OneToOne
Transportavel transportavel;

//atributos e metodos 

}[/code]

Como mapear e persisti o atributo “transportavel” da classe Container ?? :?: :?:

usar interface é uma boa prática, certo?
Um dos principios OO diz: PROGRAME PARA INTERFACE, NÃO PARA IMPLEMENTAÇÕES.

Será que o JPA não suporta mesmo o uso de interfaces (como um atributo persistente) em classes de entidade? :?: :?:
Tentei obter resposta a essa pergunta, mas em vão. Algumas pessoas sugeriram usar uma classe abstrata.

Mas ao meu ver seria melhor uma interface.

Assim,
Existe alguma solução?
É possivel usar interface no JPA?

O JPA não suporta mapeamento objeto-relacional de interfaces, apenas de classes.

Existem vários problemas na implementação de baixo nível para um mapeamento assim que são difíceis de resolver. O principal destes problemas é que não existe o conceito de polimorfismo no modelo entidade-relacionamento (modelo este que é usado por quase todos os SGBDs). Desta forma, em um relacionamento entre duas tabelas, o banco de dados subjacente deve conhecer exatamente quais são as duas tabelas e elas nunca podem variar (ou seja, não é possível que em uma coluna X da tabela Y, um registro tenha a chave estrangeira apontando a tabela A e em outro registro para a tabela B), o que no lado do java significa efetivamente se amarrar a uma implementação. Para piorar este problema, entidades diferentes podem ter chaves de formatos completamente diferentes (inclusive compostas).

Existem algumas soluções parciais que atenuam este problema (mas não o eliminam). Uma delas é definir um mecanismo de herança que é mais ou menos suportado. No entanto, este mecanismo ainda tem fortes limitações. O modelo TABLE_PER_CLASS pode te induzir a ter queries gigantescas e lerdíssimas que crescem assustadoramente cada vez que você mapeia uma subclasse a mais (usam uma série de UNIONs), além de sacrificar consistência de chave estrangeira no banco de dados subjacente. O modelo SINGLE_TABLE te leva a um modelo sem normalização com o número de colunas crescendo cada vez que você cria uma subclasse, além de te impor que todos os campos das subclasses devem aceitar valores nulos. O modelo JOINED normalmente é o melhor, mas ele também pode te trazer alguns problemas e nem sempre você pode aplicá-lo. Se você fizer um select em uma lista cujo o tipo é a superclasse, vai quebrar a cara tanto com o TABLE_PER_CLASS quanto com o JOINED, pois será criada uma série de UNIONs, mas neste ponto o JOINED é um pouco melhor que o TABLE_PER_CLASS.

No entanto, ainda existem outros problemas de baixo nível além deste que eu te falei. Um destes outros problemas é que o JPA precisaria garantir que a implementação da interface, seja ela qual for, que estivesse devidamente mapeada no banco de dados para que pudesse ser persistida, coisa que na prática não é possível de garantir. A coisa mais próxima disso é a herança com JOINED.

O Hibernate tem, por fora do JPA, uma solução parcial para este problema que permite relacionar entidades com alguma outra entidade arbitrária sem que haja uma relação de herança entre essas entidades, usando as anotações @Any, @AnyMetaDef, @AnyMetaDefs e @ManyToAny, específicas do Hibernate. Nesta solução, você especifica todos os subtipos possíveis que um determinado objeto relacionado pode ter. No entanto, você tem que especificar de antemão todas as possíveis implementações, o que vai contra a ideia de se ter interfaces (aliás, nem sei se você mapeia uma interface ou se ele exige que seja simplesmente Object, mas neste caso você resolve com um simples cast). E o resultado não é dos melhores, sai algo muito parecido com o TABLE_PER_CLASS.

Resumindo: Esqueça, o que você quer fazer não é possível. A coisa mais próxima que tem é usar herança com JOINED ou TABLE_PER_CLASS, ou usar o @Any e/ou o @ManyToAny específicos do Hibernate. Ou então reestruture a sua aplicação de forma que não necessite de nenhum tipo de mapeamento de interfaces (o que normalmente é bastante doloroso).

em JPA, as entidades são POJOS, e não implementam interfaces.

Entendi.

Então não tem como utilizar Interface no JPA para persistir dados :cry:

Bom, tomaras que nas próximas versões do JPA seja melhorado isso, pois pelo pouco que estou mexendo deu pra perceber que o JPA é uma ótima ferramenta para persistencia a dados.

Pessoal, muito obrigado pelas respostas. :thumbup:

Uma interface só pode ter atributos públicos e estáticos, não? Então, por definição (por causa do estático), uma interface nunca vai ser mapeada para o banco.

É bem diferente do caso de superclasse.

Na verdade pode implementar interface.
Ex:

[quote=bigode_java]Entendi.

Então não tem como utilizar Interface no JPA para persistir dados :cry:

Bom, tomaras que nas próximas versões do JPA seja melhorado isso, pois pelo pouco que estou mexendo deu pra perceber que o JPA é uma ótima ferramenta para persistencia a dados.

Pessoal, muito obrigado pelas respostas. :thumbup:
[/quote]
Vale lembrar q uma “interface” pode ser uma classe abstrada tb… de modo que se torna possível como o victorwss falou
Uma interface é uma abstração, algo que necessita ser implementado em outras classes. Programar para uma interface não necessáriamente é usar uma “interface java”

Então pode-se dizer que JPA NÃO desencoraja o uso de interfaces!

[quote=CintiaDR]Uma interface só pode ter atributos públicos e estáticos, não? Então, por definição (por causa do estático), uma interface nunca vai ser mapeada para o banco.

É bem diferente do caso de superclasse. [/quote]

Na verdade você pode mapear entidades também pelos pares de getters e setters. Não é este o motivo de não poder usar entidades mapeadas.

Na verdade pode implementar interface.
Ex:

Uma definição mais precisa seria de que apenas classes POJOs são mapeadas, o que não as proíbem de implementarem interfaces, mas as interfaces não são mapeadas.