Qual a importancia de se utilizar JPA ao invés de Hibernate?

57 respostas
R

Com a nova (nem tão nova assim) onda de se utilizar JPA ao invés de Hibernate, surgem as questões…

Quase todo mundo que hoje utiliza JPA, tem como implementação o Hibernate que já utilizavam anteriormente…

O JPA introduziu novas interfaces e classes além do que já tinhamos que saber com o Hibernate. Mas o JPA não é uma especificação completa porque ainda é necessário em alguns momentos utilizar coisas especificas do Hibernate.

O JPA acabou introduzindo uma nova camada de persistencia e nós sabemos que camadas em cima de camadas trazem problemas.

Se a implementação de JPA que todo mundo utiliza é o Hibernate, qual é a utilidade de se ter JPA?

57 Respostas

L

Seguinte…

Hiberante padrão não implementa JPA

vc pode usar ele direto, mas não vai conseguir usar tudo que o JPA oferece

o JPA oferece menos coisa que o Hibernate… mais oferece algumas coisas de forma diferente do hiberante com interface mais faceis…

o hiberante pra atender ao JPA criou um adaptador, o pactoe EntityManager, que implementa o JPA ou seja, ele nada mais faz que delegar pra interface do JPA os comandos corretos em uma Session…

Se vc usa Hiberante não pode usar @EntityListeners() por exemplo, para callbacks, vai ter que usar intereptors do hibernate…

Se vc usar JPA Puro, não vai ter várias coisas que só tem no Hiberante…

Solução ? cria o JPA usando o Hiberante… passa a poder usar tudo do HIBERNATE e tudo do JPA… cria os entitymanager normalmente… e pra pegar a session basta fazer

Session session = (Session)EntityManger.getDelegate();

A vantagem é que vc consegue usar os 2…

E fora isso quase todo mundo cria uma camada do seu projeto (ou com DAO, que eu desaprovo, ou com Repository, que é o que uso) …

No caso seu projeto conversa como Repository ou DAO que é um adpatador para o JPA (ou diretamenteo hibernate) que é um adaptador para a Session (no caso de usar jpa) …

Assim seu projeto passa a depender de uma estrutura propria, o Repository ou o DAO … e se omundo cair, explodir, houver uma guerra, e vc resolver mudar no proximo projeto a implementação de persistencia, vai continuar utiliando sua estrutura de DAO ou Repository, e assim sua Lógica, fica protegida dessa sua escolha de persistencia

R

Entendi…

Mas o que eu questiono é o seguinte… se na verdade você mesmo usando JPA, vai estar utilizando é o Hibernate…

Pra que JPA?? Porque nao usar o Hibernate direto como sempre foi feito?

Que vantagem tem no JPA??

(Entende o que eu quero dizer?)

L
rogelgarcia:
Entendi..

Mas o que eu questiono é o seguinte.. se na verdade você mesmo usando JPA, vai estar utilizando é o Hibernate...

Pra que JPA?? Porque nao usar o Hibernate direto como sempre foi feito?

Que vantagem tem no JPA??

(Entende o que eu quero dizer?)

não é exatamente igual.... JPA é uma interface... é uma especificação, ele não é uma implementação, ele vem pra dizer....

quer criar um pacote de persistence ? use a interface JPA, usando esssa interface vc poderá ser escolhido por quem utiliza JPA

..............

Hiberante é uma implementação real, e nã nasceu pra implementar o JPA, por isso ele tem suas proprias interfaces, e tem mais recurso que a implementação do JPA poderia pedir....

Para solucionar o Hierante criou um Adaptador.... que simplismente atende a tudo do JPA, a 100% da especificação JPA, e continua funcionando como antes, com a espcificiação do Hiberante.....

Usar hiberante sozinho, não vai ter as funcionalidades do JPA....

.................

por exemplo

@Entity
@EntityListners(Auditor.class)
public class Entidade {

}


publci class Auditor {
   @PrePersist
   void antesDePersistir(Entidade entidade) {
        entidade.setDataCriacao(new Date());
   }
}

por exemplo, se vc criar uma SessionFactory, e tentar persistir uma Entidade, ela não vai chamar o Auditor, e assim setar a data correta de criação.

Porem criando uma EntityManagerFactory, ele vai fucionar, mesmo que a implementação seja o Hiberante....

a maioria das anotações são do JPA e não do Hiberante, e anotação é melhor q xml, mais um motivo pra pelomenos instnaciar pelo JPA

R

Sim… eu sei que JPA é só uma especificação e Hibernate é uma implementação… isso é claro pra mim…

A minha questão é… pra que JPA? Qual a vantagem eu tenho em relação a usar só o hibernate?


Sobre a questão do Listener, isso é só uma forma diferente de fazer a mesma coisa que é possível fazer com hibernate…

E o hibernate tem o hibernate annotations… então trabalhar com annotations no hibernate nao é problema… mesmo sem usar JPA


O que eu quero dizer é… o Hibernate atende, inclusive melhor que se usar só a interface JPA… entao pra que eu vou querer JPA?

R

O que eu to querendo chamar a atençao… é que parece invenção de moda… entende?

L

rogelgarcia:
Sim… eu sei que JPA é só uma especificação e Hibernate é uma implementação… isso é claro pra mim…

A minha questão é… pra que JPA? Qual a vantagem eu tenho em relação a usar só o hibernate?


Sobre a questão do Listener, isso é só uma forma diferente de fazer a mesma coisa que é possível fazer com hibernate…

E o hibernate tem o hibernate annotations… então trabalhar com annotations no hibernate nao é problema… mesmo sem usar JPA


O que eu quero dizer é… o Hibernate atende, inclusive melhor que se usar só a interface JPA… entao pra que eu vou querer JPA?

A pergunta na verdade é ao contrario …

Pra que se amarrar única e exclusivamente ao Hiberante ? se eu consigo mapear todas as minhas entidades com JPA ? e assim posso usar outra Unidade de persistencia como Link por exemplo, no caso de um dia precisar ?

vc não conhece o amanha, e em java uma das boas praticas dizem… não programe para implementação, programe para a interface… e é isso que é programar para o JPA

L

por exemplo vc já deve ter cançado de ver isso escrito por ai

List<BlaBlaBla> lista = new ArrayList<BlaBlaBla>();

e vc já se perguntou ? pq não fazer

ArrayList<BlaBlaBla> lista = new ArrayList<BlaBlaBla>();

já que uma arraylist é mais poderosa que apenas a interface ? afinal a arraylista tem implementações, e pode ter propriedades únicas....

o problema de fazer isso é que vc amarra a droga da ArrayList, e existem outros tipos de lista por ai!

e se vc fizer um método
public void queroUmaLista(ArrayList<?> meDaAlista) {

}

vai acabar se ferrando, pq por exemplo, a lista do Hiberante é uma PersistenceBag, e não uma ArrayList, e não vai conseguir usar....

subindo o nivel, para a interface mais abrangende, vc abre o leque de opções.....

public void queroUmaLista(List<?> meDaAlista) {

}

tem um nivel de acoplamento muito mais baixo.... pois aceita muito mais gente

e digo mais! se dentro dessa lógica, vc tiver apenas um FOR, mesmo que em seu projeto vc saiba que só tem list, vc deve escrever Collection<?> e não List<?>

por isso

public void queroUmaLista(Collection&lt;?&gt; meDaAlista) {
      for(Object item : meDaAlista) {
            //tem muito mais reusabilidade que os códigos acimas
      }
}
R

Acho que é muito improvavel alguém trocar de implementacao de JPA, isso é trocar seis por meia dúzia…
E aposto o que for… que nessa troca vão haver bugs… pois não teria vantagem trocar de implementacao a nao ser pra usar as coisas especificas…

Pelo que eu já vi na minha vida isso nao funciona… é bonito na teoria mas na pratica é diferente…

E pra voce chegar a trocar isso o sistema tem que ser tão antigo… e vai ter tantas coisas novas… e incompatíveis com o que já foi feito…

Valeria a questão das várias implementações de JPA… se a especificação fosse boa…

JPA na verdade foi criado baseando-se no hibernate… Fizeram ao contrário da sua lógica… primeiro fizeram a implementacao… depois a interface… ou seja… a interface ficou atrelada a implementacao do mesmo jeito…

Mas valeu seus comentários… vamos ver como esse negócio de JPA caminha…
Na minha humilde opinião… só tá servindo pra complicar :smiley:

R

O exemplo da lista eu considero mais pertinente que o JPA… pois a interface é bem definida… e tem várias implementacoes… uma para cada situacao…

R

Acho que o povo gasta fosfato demais pensando coisas cabulosas… em vez de pensar no simples…

quer ver um exemplo

A anotação @ManyToOne… já é fetch EAGER por default…

se vc quiser LAZY tem que colocar em todas as annotacoes…

olha que saco… ao invés de vc configurar isso uma vez só na sua aplicacao…

Ao invés de o povo preocupar com coisa útil… fica viajando… em super arquiteturas…

Por isso os Rails tao aí dominando tudo… é facil e tem um jeito de fazer e bem feito…

L

nop, JPA foi criada para o Link, que era da oracle, e foi passada a eclipse fundation, e a implementação do JPA2 que tem muita base no hiberante, principalmente em criteria…

O reuso não é exatamente do seu projeto, vc não vai pegar seu projeto, e apagar o Hiberante e enfiar um TopLink um EclipseLink ou coisas do tipo…

Mas vc pode se ver na situação de pegar um projeto usando EclipseLink, e simplismente não conhecer nada de JPA e nada de EclipseLink, e acabar não conseguindo reutilizar nada que ja usou na vida, apesar de ter anos de experiencia com ORM não vai conseguir se dar bem nesse novo projeto…

o que vc reusa são os componentes, por exemplo… eu tenho várias entidadees, que dou CTRL+C e CTRL+V em novos projetos… e não tenho que alterar 1 virgula…

se pegar um projeto diferente do meu mundo, pelomenos eu escrevi elas para algo de aceitação geral…

por exemplo,

se vc escrever

session.save(entity); … só vai reusuar em ambiente com hibernate

se usar entityManger.persist(entity); … já vai poder reusuar em qualquer ambiente com JPA, e isso inclui o proprio hiberante

se usar repository.add(entity) … vai poder escrever seu repositorio, e poder reusar a lógica criada em qualquer lugar

e se seu novo projeto não for com hiberante, vc precisará reescreverapenas o repositorio, mas nunca reescrever todo chamada a um .persist, ou .save

e não to falando isso pq é bonito, ou é lindo na teoria, isso é pratica, e enclusive se chama boas praticas ^^

M

Tópico legal…

A Sun sempre faz isso… pega as boas idéias do mercado e documenta… específica, padroniza, acho muito legal isso…
Ao meu ver a única vantagem mesmo de utilizar em uma implementação JTA, apenas o que está especificado pela Sun, é a possibilidade de troca da implementação…
Mas, convenhamos, ninguém faz isso, como já foi dito anteriormente…

abss

R

Entendi… a proposta… é um ambito maaaiorrr do que eu estava pensando…

Pro projeto que eu faço aqui … nao tem validade mesmo nao…

Tem caso eu for passar esse projeto pra alguém… ele vai estar mais padronizado…

(eu to ligado nas boas praticas… eu concordo também… mas o que fico indignado é que ao invés de resolver o problema mesmo… o povo fica querendo crescer e crescer e inventando coisas… se o que já existe nem tá tao bom assim…
já fuçei muito o código do hibernate… que tragédia… de boas práticas aquilo passou longe… hahhah)

Eu uso o hibernate… mas acho ele muito limitado… mas num tem outro né?!

L

rogelgarcia:
Entendi… a proposta… é um ambito maaaiorrr do que eu estava pensando…

Pro projeto que eu faço aqui … nao tem validade mesmo nao…

Tem caso eu for passar esse projeto pra alguém… ele vai estar mais padronizado…

(eu to ligado nas boas praticas… eu concordo também… mas o que fico indignado é que ao invés de resolver o problema mesmo… o povo fica querendo crescer e crescer e inventando coisas… se o que já existe nem tá tao bom assim…
já fuçei muito o código do hibernate… que tragédia… de boas práticas aquilo passou longe… hahhah)

Eu uso o hibernate… mas acho ele muito limitado… mas num tem outro né?!

esse é o fato… tem outro sim… e épra isso que o JPA esta ai… pra ter muitooosssss outros…

antes só existia as coleções do Java Collections Framework… hoje quase todo mundo usa as do google pq são melhores (sem falar que a um tempinho atras tinhas ainda as da apache)… imagina se vc programasse pra implmentação ? apenas por saber que… implentação X é a melhor ?

Exite TopLink, EclipseLink, que seriam como versão 1 e 2, de uma mesma base… existem mais, acredito, mas pelomenos tem essas

o EclipseLInk vem como padrão no Eclipse, e tem muita gente que usa… claro que nem se compara a quantidade que usa hiberante…

pensar só no seu projeto, vc não vai longe… com certeza um dia, vc vai mudar de projeto, e abranger a quantidade de código que vc possa reusar é bom, na hora de mudar de abordagem

R

Eu falei que nao tinha outro… nao tinha outro bom… ou que fizesse a mesma coisa… que o hibernate

Já tentei trabalhar com esses outros…mas eles pecam mais do que o hibernate ainda… nao gostei…

Acho que entao a filosofia de se construir o JPA teria que ser diferente… partindo de uma interface bem pensada… e nao de implementacoes…

Voce tem que programar para interfaces… concordo plenamente… mas e se a interface é ruim?!

O JPA em si é valido… como tá sendo feito é que eu acho que nao é…

R

Eu mesmo já pensei numa especificacao de um framework de persistencia… muito mais flexivel que o hibernate por exemplo…

Se o JPA se limitar ao que o Hibernate faz… nao vai adiantar nada…

L

já leu sobre o JPA 2 ?

a especificação na verdade é um ponto de convergencia....

dificlmente uma especificação vai correr a frente da implementação.... afinal novas ideias aparecem o tempo todo... e a especificação é um conjunto das melhores.... e tenta reunir tudo em um sento comum e ponto comum....

realmente tem loucuras de bancos legados que é foda de fazer com JPA e da dor de cabeça.... e vc acaba usando anotações do Hiberante.... mas no geral, pra anotaçõeso JPA cobre tudo.... desde que não seja um banco maluco legado...

...........

Para buscas, eu não troco os Criterias pelas HQLs do JPA, mas também não exponho elas para meu projeto, e uso objetos Queries, para meu projeto não tercontato com o Hiberante, e sim com uma interface de mais alto nivel....

assim posso continuar reusando.... por exemplo, trocar do Hiberante 3 para a proxima versão que vai implementar o JPA 2, vai ser relativamente fácil para meus projetos, pois só vou reescrever a camada de persistencia, um conjunto de 8 classes no máximo.

Lógico que não vou pegar meu projeto que ta escrito com criterias 3.x, e com hiberante e etc, e enfiar o Hibernate novo para JPA 2, pq isso seria sem sentido... porem vou conseguir reusuar a mesma lógica em novos projetos, sem ser afetado pela camada de persistencia...

..........

Obs.: eu entendo sua revolta... já pensei igual, mas me ajudar muito, conseguir não programar diretamente com o hiberante....

aqui vai um exemplo de código em meus projetos...

repository.addAll(carros);
repoistory.removeAll(telefones);

List&lt;PessoaFisica&gt; pessoasAtivas = queries.forPessoa().listPessoasAtivas().queryOn(repository);

todas são de facil leitura, Repository éuma INterface.... e a implementação normal que uso é pra Hiberante.... mas já precisei usar pra SQL puro entre outras firulas, por questões diversas

..........

em momento algum em meu projeto há um new HibernateRepository .... quando não uso algo como spring, o HiberanteRepository vem sempre de algo como

Repository repository = minhaFabrica.createRepository();

no caso é só trocar o que vem do CreateRepository e voala! .... mudo a implementação facilmente...

R

Muito legal cara… to vendo que voce é um cara conhecedor do assunto…

Fiquei curioso sobre o Repository… tem algum artigo interessante sobre isso?

Procurei na internet mas só vi gente perguntando sobre a diferença entre repository e dao e poucas explicacoes…

L

eu iniciei lendo no blog do sergio taborda http://sergiotaborda.wordpress.com/desenvolvimento-de-software/java/patterns/repository/

depois fui fazendo a minha maneira…

A entender, a diferenca basica do DAO pro RESPOSITORIO, e’ que o DAO acumla as queries dentro dele, e por isso vc sai criando 1 DAO por Entidade… isso traz dificuldade, pois uma Session funciona com um repositorio, ela funciona igual seja a entidade qual for…

Entao o repositorio tem aceita objetos em seus metodos, e asism repository.add(Object o); e assim para cada operacao,

Tudo que for generico vc deixa no repositorio, ou seja

<T> List<T> repo.list(Class<T> target);

<T> T repo.get(Class<T> target, Object id);

repo.refresh(Object object);

etc etc etc

e as queries as consultas, vc separa coloca em outro objeto, eu crirei uma interface pra fazer isso…

e no fim, eu executo uma Query em um Repository,

que para o hiberante eu so faco pegar um DatechedCriteria que esta dentro do queries, e unir a session dentro do repository, e assim a magica da consulta acontece…

B

Ótimo tópico, não vejo grandes diferenças não, como já falado anteriormente acho bacana a Sun trazer algo de sucesso para especificação…

A JPA por se tratar de uma abstração que funciona independente de uma implementação específica te permite
ter alternativas ao Hibernate(claro que a implementação dele é a melhor entre outras), te possibilitando uma flexibilidade de escolha, acho isto um quesito muito importante quando se trabalha com boas práticas de OO…

Como já falado, outro obstaculo a JPA seria o Criteria, mas já foi inserido na especificação 2.0 com alguns recursos de tipagem não existentes no Hibernate…

Rogel deixa de ser chato e teimoso e usa o JPA… :smiley:

R

Hahahah… blza Breno…

Só estou estressando as possibilidades para ver qual é a melhor alternativa…

Se vou usar alguma coisa… tenho que ter motivos para isso… to procurando os motivos…

Não gosto de usar alguma coisa só pq um povo que nem programa no dia a dia definiu… (já vi muitas definicoes ruins desse pessoal)

R

Vejamos esse mapeamento (eliminei os getters e setters para simplificar):

@Entity
public class Produto {

	@Id
	@GeneratedValue(strategy=SEQUENCE, generator="sq_produto")
	@SequenceGenerator(name="sq_produto", sequenceName="sq_produto")
	Integer id;
	String nome;
	@ManyToOne(fetch=FetchType.LAZY)
	Tipo tipo;

Isso poderia ser feito assim:

public class Produto {

	Integer id;
	String nome;
	Tipo tipo;

Todas as informações do mapeamento já estão na classe…
Eu poderia configurar no meu persistence.xml
Todos as classes do pacote com.company.persistence são entidades
Os atributos com nome id são @Id
Todos os @id devem usar um sequence com nome sq_{nomedaclasse}
É óbvio que Tipo é um @ManyToOne… e poderia definir que todos os @ManyToOne são lazy

Pronto… eu configuraria meu padrão uma vez na minha app… e não precisaria lotar minha classe com anotations… isso sim… é uma coisa prática… que ajuda no sistema e diminui o acoplamento

Agora o povo fica só pensando em coisas do reino da imaginacao que no dia a dia nem tem tanta importancia

M

Lavieri

poderia explicar melhor esta estrutura:

pelo que eu entendi queries é uma classe onde vc pode pegar objetos de consulta especificos de cada classe do mdoelo, no caso o forPessoa retorna um desses objetos pra classe Pessoa. nesses objetos estão as queries especificas de pessoas, como no exemplo listPessoasAtivas. só não entendi o que esse query on retorna, acho que é um obejto que sabe qual query a ser executada no repositório, mas não estou com certeza disso.

Achei muito bacana, quero entender pra montar algo do tipo.

[]'s

R

Outra coisa...

Imagine que eu tenho a classe Mestre e a classe mestre tenha uma List de Detalhe

class Mestre {

     List<Detalhe> detalhes;
}

Se eu anotar os detalhes com aqueles cascades todos.. pra ficar tudo automático...

Como eu faço se eu quiser alterar só o Mestre e não quiser mecher nos Detalhes? Se eu mandar persistir o Mestre sem Detalhe nenhum (lista vazia).. o JPA/Hibernate vai apagar todos os meus detalhes..

B
rogelgarcia:
Outra coisa...

Imagine que eu tenho a classe Mestre e a classe mestre tenha uma List de Detalhe

class Mestre {

     List<Detalhe> detalhes;
}

Se eu anotar os detalhes com aqueles cascades todos.. pra ficar tudo automático...

Como eu faço se eu quiser alterar só o Mestre e não quiser mecher nos Detalhes? Se eu mandar persistir o Mestre sem Detalhe nenhum (lista vazia).. o JPA/Hibernate vai apagar todos os meus detalhes..

Bom, com o que vc tem hj tem como fazer apenas de forma estática, insertable = false ...

A
rogelgarcia:
Outra coisa...

Imagine que eu tenho a classe Mestre e a classe mestre tenha uma List de Detalhe

class Mestre {

     List<Detalhe> detalhes;
}

Se eu anotar os detalhes com aqueles cascades todos.. pra ficar tudo automático...

Como eu faço se eu quiser alterar só o Mestre e não quiser mecher nos Detalhes? Se eu mandar persistir o Mestre sem Detalhe nenhum (lista vazia).. o JPA/Hibernate vai apagar todos os meus detalhes..

Não entendi o cenário. Pq detalhes esta vazio? Ele poderia estar com o proxy Lazy de sua representação no banco, e vc alterar os outros atributos de Mestre normalmente. Uma coisa não tem haver com outra.

R

Eu poderia estar com um Mestre desatachado da sessao… que eu quisesse persistir… (mas a lista de Detalhe está vazia)

Eu gostaria de só alterar o Mestre… mas se eu pedir pra salvar o Mestre desse jeito… o hibernate também deleta o detalhe…

A

Tem vários motivos para vc iniciar um projeto com JPA, a maioria já foi explanado aqui, mas vamos lá:

  • Bootstrap facilitado: HibernateUtil é um “workaround” necessário para se construir a SessionFactory. Já vi muita implementação meia boca estourando memória por causa disso. O JPA em ambiente JavaEE é bem mais eficiente em sua inicialização com o apoio do persistence.xml, autodiscovery das classes anotadas e gerencia do EntityManager feita automaticamente pelo container (abri, fechar, descarregar e injetar).

  • D.I. - Uma vez fazendo parte da especificação, ele se beneficia de todos os demais recursos enterprises, sobre injeção de dependencia e todo seu ciclo de vida. No JavaEE 6, isso esta ainda melhor, uma vez que não apenas EJBs podem se beneficiarem com isso, mas qualquer bean.

  • Portabilidade (menos relevante) - nao considero isso a melhor feature para iniciar um projeto com JPA, pq EU utilizao muita coisa do Hibernate. Mas para quem preza por independecia de implementação pode ser um atrativo.

O fato é, 99,9% das vezes inicio os projetos com JPA. Quando algo nao me atende entao getDelegate para obter a session do hibernate, sem pestanejar. Mas nao perco a integração com o ambiente JavaEE e nem seu bootstrap que é uma mao na roda.

A

rogelgarcia:
Eu poderia estar com um Mestre desatachado da sessao… que eu quisesse persistir… (mas a lista de Detalhe está vazia)

Eu gostaria de só alterar o Mestre… mas se eu pedir pra salvar o Mestre desse jeito… o hibernate também deleta o detalhe…

Mas “PQ” detalhe esta vazia???
Se Mestre esta detachado e vc faz “Merge”, ele nao apaga sua lista, ele relinka os proxies de Detalhe, que NAO esta vazio.
A não ser que vc tenha construído o Mestre com “new”, o que nao deveria ser feito.

L
mario.fts:
Lavieri

poderia explicar melhor esta estrutura:

queries.forPessoa().listPessoasAtivas().queryOn(repository);

pelo que eu entendi queries é uma classe onde vc pode pegar objetos de consulta especificos de cada classe do mdoelo, no caso o forPessoa retorna um desses objetos pra classe Pessoa. nesses objetos estão as queries especificas de pessoas, como no exemplo listPessoasAtivas. só não entendi o que esse query on retorna, acho que é um obejto que sabe qual query a ser executada no repositório, mas não estou com certeza disso.

Achei muito bacana, quero entender pra montar algo do tipo.

[]'s

queries e' uma fachada.... ele conhece os caminhso para os objetos que conhece a query de cada entidade...
public class Queries {
      public PessoaQuery forPessoa() {
            return PessoaQuery.getInstance();
      }
      public ImovelQuery forImovel() {
            return ImovelQuery.getInstance();
      }
}
//ou seja apenas uma facahada.....

PessoaQuery contem todas as querys para pessoas

public class PessoaQuery {
     public QueryableList<Pessoa> listarAtivas() {
           DatechedCriteria dc = DatechedCriteria.forClass(Pessoa.class)
               .add(Restrictions.eq("ativo",true);
           return new HibernateQuery<Pessoa>(dc).list();
     }
     
     public Queryable<Pessoa> byCpf(String cpf) {
           //...
           return new HibernateQuery<Pessoa>(dc).unique();
     }
}

QueryableList e' uma interface

public Queryable<T> {
     T queryOn(Repository rep);
}

public QueryableList<T> extends Queryable<List<T>> {
     List<T> queryOn(Repository rep,int startPosition);
     List<T> queryOn(Repository rep,int startPosition,int maxResults);
}

HiberanteQuery e' uma classe que retorna Queryable ou QueryableList

public HiberanteQuery<T> {
      public HiberanteQuery<T>(DetachedCriteria dc) {this.dc = dc}
      Queryable<T> unique();
      Queryable<T> first();
      Queryable<Integer> count();
      QueryableList<T> list();
}

a implementacao desses metados e' juntar a session do Repository com a DatechedCriteria que e' passado no construtor.

e assim retorna a consulta tipada que esta definida no queryable ou queryablelist

M

Muito bom cara, vou montar um esquema assim pra testar.

Valeu.

S

rogelgarcia:
Com a nova (nem tão nova assim) onda de se utilizar JPA ao invés de Hibernate, surgem as questões…

Quase todo mundo que hoje utiliza JPA, tem como implementação o Hibernate que já utilizavam anteriormente…

O JPA introduziu novas interfaces e classes além do que já tinhamos que saber com o Hibernate. Mas o JPA não é uma especificação completa porque ainda é necessário em alguns momentos utilizar coisas especificas do Hibernate.

O JPA acabou introduzindo uma nova camada de persistencia e nós sabemos que camadas em cima de camadas trazem problemas.

Se a implementação de JPA que todo mundo utiliza é o Hibernate, qual é a utilidade de se ter JPA?

Nenhuma. A utilidade do JPA é nenhuma.
Depois que o pessoal do Core Patterns JEE levou na cabeça , e depois que o Hibernate foi criado foi desenvolvido o padrão DomainStore.
É este padrão que o JPA tenta implementar.
O JPA nasceu como uma alternativa OO ao JDBC mas ao contrario deste ele nasceu falho. O conceito de Native Query é completamente idiota
porque mata o objetivo de ter um mecanismo portável entre bancos. Da mesma forma que o JDBC precisa de um mecanismo para o adquar a vários bancos o JPA precisa do mesmo. O Hibernate não precisa.

O sucesso do hibernate se deve ao padrão DomainStore e ao fato de ser free. Hoje em dias temos opções como Eclipse Link, mas aprender a usar mais uma ferramenta ORM é chato p’rá caramba.

Usar o JPA é na realidade um erro no contexto geral e só justificavel se vc quiser aderir às normas de portabilidade JEE, que todo o mundo já sabe são falhas em si mesmas.

É um falso argumento que precisamos do JPA para isolar o hibernate. Isso é feito facilmente com objetos criados por nós mesmos usando padrões como bridge e strategy. Eu nunca usaria JPA por escolha.

S

Lavieri:
eu iniciei lendo no blog do sergio taborda http://sergiotaborda.wordpress.com/desenvolvimento-de-software/java/patterns/repository/

depois fui fazendo a minha maneira…

A entender, a diferenca basica do DAO pro RESPOSITORIO, e’ que o DAO acumla as queries dentro dele, e por isso vc sai criando 1 DAO por Entidade… isso traz dificuldade, pois uma Session funciona com um repositorio, ela funciona igual seja a entidade qual for…

Entao o repositorio tem aceita objetos em seus metodos, e asism repository.add(Object o); e assim para cada operacao,

Tudo que for generico vc deixa no repositorio, ou seja

<T> List<T> repo.list(Class<T> target);

<T> T repo.get(Class<T> target, Object id);

repo.refresh(Object object);

etc etc etc

e as queries as consultas, vc separa coloca em outro objeto, eu crirei uma interface pra fazer isso…

e no fim, eu executo uma Query em um Repository,

que para o hiberante eu so faco pegar um DatechedCriteria que esta dentro do queries, e unir a session dentro do repository, e assim a magica da consulta acontece…

Incrível, mas eu quiz dizer exatamente o contrário do que vc entendeu.
O Repositório não é genérico nem agnóstico, ele é concreto e associado a uma única entidade. O repositório cria as queries, ele não executa as queries.
Cada repositorio especifico contém métodos para encontrar aquele tipo de entidade, conforme critérios que fazem sentido para ela. Pode conter métodos gerais comuns a todas as entidades como save e delete, mas fortemente tipados para aceitar apenas aquele tipo de entidade. nisto os repositorios em nada são diferentes dos antigos DAO.

A diferença entre DAO e Repositório é que o DAO é um tradutor de tecnologias (ORM, OXM, etc…) Repositório é um encapsulador de regras de pesquisas e um ponto centrar para procurar objetos daquela entidade.

vou ter que mehlorar esse artigo :oops: …

R

Alessandro Lazarotti:
Tem vários motivos para vc iniciar um projeto com JPA, a maioria já foi explanado aqui, mas vamos lá:

  • Bootstrap facilitado: HibernateUtil é um “workaround” necessário para se construir a SessionFactory. Já vi muita implementação meia boca estourando memória por causa disso. O JPA em ambiente JavaEE é bem mais eficiente em sua inicialização com o apoio do persistence.xml, autodiscovery das classes anotadas e gerencia do EntityManager feita automaticamente pelo container (abri, fechar, descarregar e injetar).

  • D.I. - Uma vez fazendo parte da especificação, ele se beneficia de todos os demais recursos enterprises, sobre injeção de dependencia e todo seu ciclo de vida. No JavaEE 6, isso esta ainda melhor, uma vez que não apenas EJBs podem se beneficiarem com isso, mas qualquer bean.

  • Portabilidade (menos relevante) - nao considero isso a melhor feature para iniciar um projeto com JPA, pq EU utilizao muita coisa do Hibernate. Mas para quem preza por independecia de implementação pode ser um atrativo.

O fato é, 99,9% das vezes inicio os projetos com JPA. Quando algo nao me atende entao getDelegate para obter a session do hibernate, sem pestanejar. Mas nao perco a integração com o ambiente JavaEE e nem seu bootstrap que é uma mao na roda.

Pois então… tudo isso que voce falou aí … chegou atrasado… já existem essas features a 5 anos no framework que eu criei :smiley:

Pros projetos que eu uso então… nao teria vantagem… a nao ser a questao de portabilidade que é o menos importante…

E se eu quiser usar o JPA no desktop… é trivial?

R

Alessandro Lazarotti:
rogelgarcia:
Eu poderia estar com um Mestre desatachado da sessao… que eu quisesse persistir… (mas a lista de Detalhe está vazia)

Eu gostaria de só alterar o Mestre… mas se eu pedir pra salvar o Mestre desse jeito… o hibernate também deleta o detalhe…

Mas “PQ” detalhe esta vazia???
Se Mestre esta detachado e vc faz “Merge”, ele nao apaga sua lista, ele relinka os proxies de Detalhe, que NAO esta vazio.
A não ser que vc tenha construído o Mestre com “new”, o que nao deveria ser feito.

A parte controller da minha app… pode ter criado o Mestre… entao será com new por exemplo

S
Lavieri:
j
repository.addAll(carros);
repoistory.removeAll(telefones);

List&lt;PessoaFisica&gt; pessoasAtivas = queries.forPessoa().listPessoasAtivas().queryOn(repository);

Isto que vc desenhou não é um repositorio é um DAO. Repositorios são usados assim

Repositorio&lt;Pessoa&gt; rep = ...

List&lt;Pessoa&gt; pessoasAtivas = rep.listPessoasAtivas();

O codigo não sabe qual é o critério que define que a pessoa é ativa. Nem sabe como procurar essa especie de pessoas

Dentro do Repositorio vc tem isto

public List&lt;Pessoa&gt; listPessoasAtivas(){

        Criteria c = CriteriaBuilder.find(Pessoa.class)
                          with("ativo", true);

        return persistanceStategy.executeCriteria(c)

}

Repare que o query é em cima da persistanceStategy. Que pode ser um DAO ou domainStore

O importante aqui é que a criação do critério de busca é no proprio repositório. É essa a sua principal função : encapsular a criação dos critérios.

L

sergiotaborda:

O codigo não sabe qual é o critério que define que a pessoa é ativa. Nem sabe como procurar essa especie de pessoas

Dentro do Repositorio vc tem isto

public List&lt;Pessoa&gt; listPessoasAtivas(){

        Criteria c = CriteriaBuilder.find(Pessoa.class)
                          with("ativo", true);

        return persistanceStategy.executeCriteria(c)

}

Repare que o query é em cima da persistanceStategy. Que pode ser um DAO ou domainStore

O importante aqui é que a criação do critério de busca é no proprio repositório. É essa a sua principal função : encapsular a criação dos critérios.

Bom o nome pode não ser esse… masss o que eu não gosto do DAO é justamente o fato de ser tipado, e de ter as queries dentro dele, ter que usar 192382938 lugares para adicionar e remover entidades é o ponto onde não gosto… e pra mim isso é dar um passo pra traz.

O Hiberante aceita qualquer objeto em suas sessions, e vc encapsular a session e restringir isso pra mim é tiro no pé.

O meu repositorio, é realmente o que diz o nome, é um lugar onde se guarda onde se armazena as entidades, é possivel adicionar, remover, atualizar buscar entidades dentro dele.

O queries faz parte da camada de persistencia, e vem justamente para não ter q existir [telefone removido] repositorios e existir apenas 1, o único objetivo é desassociar as consultas do repositorio e assim não ter q existir vários locais, ou seja, varios repositorios.

queries.forPessoa().listPessoasAtivas().queryOn(repository);

é apenas pq é muito mais legal 1 repositorio, um único lugar

do que ter

repoPessoa.listPessoasAtivas();

repoCarro.listCarrosByAno(2005);

repoEtc.procureEtcPorCriterioX(x);

enfim isso é xato, é extremamente chato!

repository.forPessoas().listPessoasAtivas(); poderia ate ser… mais ai eu tenho que juntar ao repository, e meu repositorio independe de projeto.

enfim, o conceito que vc viu pode ate ser de ser tudo junto, mas desassociar me da mais flexibilidade, e não tenho intenção de abrir mão disso ^^

L

mario.fts:
Muito bom cara, vou montar um esquema assim pra testar.

Valeu.

ahhh

eu também tenho objetos Executables, que é uma interface e tem apenas o método para executar

public interface Executable { int executeOn(Repository repo); }

serve para algo como

A

rogelgarcia:
Alessandro Lazarotti:
rogelgarcia:
Eu poderia estar com um Mestre desatachado da sessao… que eu quisesse persistir… (mas a lista de Detalhe está vazia)

Eu gostaria de só alterar o Mestre… mas se eu pedir pra salvar o Mestre desse jeito… o hibernate também deleta o detalhe…

Mas “PQ” detalhe esta vazia???
Se Mestre esta detachado e vc faz “Merge”, ele nao apaga sua lista, ele relinka os proxies de Detalhe, que NAO esta vazio.
A não ser que vc tenha construído o Mestre com “new”, o que nao deveria ser feito.

A parte controller da minha app… pode ter criado o Mestre… entao será com new por exemplo

Será como não, SERA de fato um new. Se o seu controller criou o Mestre, e não buscou do banco, então é um novo Mestre, o detalhe obivamente é vazio e faz sentido que seja - o estado do objeto é transiente. Se você quer ter uma referência ao banco sem ter problema de reescrita em um campo que vc nao esta utilizando, utilize “getReference” em vez de “find”. Ele passa seu objeto ao estado persistent, sem carregar nada, nem mesmo ir ao banco, apenas adiciona proxies. Como vc quer apenas setar uma propriedade, essa seria a escolha correta (sem entrar no mérito do batch update).

A

rogelgarcia:

Pois então… tudo isso que voce falou aí … chegou atrasado… já existem essas features a 5 anos no framework que eu criei :smiley:

Pros projetos que eu uso então… nao teria vantagem… a nao ser a questao de portabilidade que é o menos importante…

E se eu quiser usar o JPA no desktop… é trivial?

Então seu framework chegou atrasado, estas features já existiam a muito mais tempo na integração do Spring com HIbernate, por exemplo. Mas sua pergunta não foi essa, e sim - “Qual a importancia de se utilizar JPA ao invés de Hibernate?” - não somado a utilização de outros framework.

Utilizar JPA em Desktop tem os mesmos problemas de utilizar Hibernate em Desktop. Com a vantagem de você poder utilizar o Persistence.createEntityManagerFactory(“blablabla”) em vez de implementar o HibernateUtil.

A

Embora discorde dos pontos que vc colocou, Taborda, como justificativa a NUNCA usar JPA, eu respeito. Faço isso por conhecer e ter trabalhado com pessoas que tem a mesma visão que a sua. Na minha opinião é uma decisão de arquitetura, tem gente que gosta, tem gente que não.

Mas gostaria realmente de enteder alguns destes pontos que vc colocou. Por exemplo:

sergiotaborda:
O JPA nasceu como uma alternativa OO ao JDBC mas ao contrario deste ele nasceu falho. O conceito de Native Query é completamente idiota
porque mata o objetivo de ter um mecanismo portável entre bancos. Da mesma forma que o JDBC precisa de um mecanismo para o adquar a vários bancos o JPA precisa do mesmo. O Hibernate não precisa.

Pq nasceu falho e o que isso tem haver com nativeQuery? Na verdade o próprio Hibernate tbm tem suporte a queries nativas através de session.createSQLQuery, exatamente da mesma forma que entityManager.nativeQuery. Assim como no hibernate, utiliza querys nativas quem quer por própria conta e risco, ou pode usar JPQL ou Criteria com a APi da especificação, como vc usa HQL com o HIbernate Core.

A
Lavieri:
mario.fts:
Lavieri

poderia explicar melhor esta estrutura:

queries.forPessoa().listPessoasAtivas().queryOn(repository);

pelo que eu entendi queries é uma classe onde vc pode pegar objetos de consulta especificos de cada classe do mdoelo, no caso o forPessoa retorna um desses objetos pra classe Pessoa. nesses objetos estão as queries especificas de pessoas, como no exemplo listPessoasAtivas. só não entendi o que esse query on retorna, acho que é um obejto que sabe qual query a ser executada no repositório, mas não estou com certeza disso.

Achei muito bacana, quero entender pra montar algo do tipo.

[]'s

queries e' uma fachada.... ele conhece os caminhso para os objetos que conhece a query de cada entidade...
public class Queries {
      public PessoaQuery forPessoa() {
            return PessoaQuery.getInstance();
      }
      public ImovelQuery forImovel() {
            return ImovelQuery.getInstance();
      }
}
//ou seja apenas uma facahada.....

PessoaQuery contem todas as querys para pessoas

public class PessoaQuery {
     public QueryableList<Pessoa> listarAtivas() {
           DatechedCriteria dc = DatechedCriteria.forClass(Pessoa.class)
               .add(Restrictions.eq("ativo",true);
           return new HibernateQuery<Pessoa>(dc).list();
     }
     
     public Queryable<Pessoa> byCpf(String cpf) {
           //...
           return new HibernateQuery<Pessoa>(dc).unique();
     }
}

QueryableList e' uma interface

public Queryable<T> {
     T queryOn(Repository rep);
}

public QueryableList<T> extends Queryable<List<T>> {
     List<T> queryOn(Repository rep,int startPosition);
     List<T> queryOn(Repository rep,int startPosition,int maxResults);
}

HiberanteQuery e' uma classe que retorna Queryable ou QueryableList

public HiberanteQuery<T> {
      public HiberanteQuery<T>(DetachedCriteria dc) {this.dc = dc}
      Queryable<T> unique();
      Queryable<T> first();
      Queryable<Integer> count();
      QueryableList<T> list();
}

a implementacao desses metados e' juntar a session do Repository com a DatechedCriteria que e' passado no construtor.

e assim retorna a consulta tipada que esta definida no queryable ou queryablelist

Quanta complicação. :shock: Qual o objetivo disto tudo?
Crie um Repository (Interface sobre uma DAO ou como uma classe Concreta) e seja feliz!

L

eu sou feliz, vc nao ?

o objetivo e’ tornar o codigo claro, legivel, e separar a camada de persistencia do restante do projeto.

nao pense que fico la escrevendo o queries o tempo todo, e que la tem consultas q eu nao preciso por exemplo…

o processo e’ simples

queries.forPessoas().[color=red]listPessoasAtivas()[/color]

nesse ponto eu aperto CTRL + 1 … no eclipse, ele cria o metodo na classe, eu escrevo o DetachedCriteria rapidinho e pronto, volto pra logica

depois sempre que precisa fica la no mesmo canto a consulta…

eu trabalho em varios projetos ao mesmo tempo, todos com o mesmo pacote basico, e com a mesma estrutura … trabalhar em um com centanas de dao, pode ser bom, mas quando trabalhe com varios e’ so ter 2 objetos para camada de persistencia (o Repositorio e o Queries) e’ simplismente otimo

S

um lugar onde se guardam e retornam objetos de qualquer tipo é um DomainStore. É por isso que vc consegue criar uma implementação baseada no Hibernate porque ele tb é um DomainStore. Vc está simplesmente desacoplando o conceito da implementação. Mas ao trocar o nome do conceito vc está fazendo um mal a si mesmo.

O repositório é um objeto que cria criterios e os envia ao DomainStore para serem executados.
No seu caso, vc tem uma classe com métodos estáticos que lhe dão a query que precisa e executa em cima do domainStore ( o que vc chama de reposiotorio é na realidade um DomainStore).

A sua arquitetura não tem Repositorios.

Vc não tem [telefone removido] repositorios mas tem [telefone removido] métodos estáticos numa classe. Qual vc acha que é melhor prática ?
Um consulta rápida na internet lhe mostrará que coisas estáticas são evil. A principal razão é que não são testáveis (porque não são “mokáveis”).
Aposto que vc não tem testes para essa classe.

Errado. Primeiro as queries fazem parte da camada de dominio. É um erro comum achar que fazem parte da persistencia, mas não fazem. Elas mudam conforme as regras do dominio e conforme a organização do dominio, logo são da camada de dominio.
Segundo, tudo bem que desassocie as consultas do local onde os objetos estão (DomainStore) , mas o problema aqui é a criação e controle dessas queries, não as queries em si, nem o DomainStore. E é ai que entra o padrão Repository

Não é uma questão de ser legal ou não. É uma questão de ser flexivel, desacoplado, de facil manutenção e testável.

A

Calma que eu não disse que vc não era feliz, apenas usei uma expressão. Nem te conheço, como posso dizer uma coisas destas. :slight_smile:

Eu que eu acho é que a abstração da persistência que o Hibernate, por exemplo, fornece é mais que o suficiente.
Então porque não usar uma classe Repository apenas e implementar a buscas usando o Hibernate diretamente.

Senão eu tenho a impressão se estar usando a abstração da abstração da abstração da …
E ter um repositório de queries, da maneira proposta, não me parece promover o reuso.

L

hmmm, [telefone removido] métodos estáticos

vc tem certeza que leu parte do codigo que coloquei aqui ?? te desafio a achar 1 metodo estatico sequere, fora o padrao singleton, que vc mesmo sabe que e’ boa pratica.

Nao ha metodos estaticos, nao ha necessidade deles, meus objetos sao concretos,

O que tenho e uma fachada, o que e’ outro padrao.

public class Queries { public PessoaQuery forPessoa() { return PessoaQuery.getInstance(); } }

Queries e’ uma fachada, serve apenas como concentrador para os varios objetos do tipo Query, como o PessoaQuery.

esses objetos sao singleton, pq nao vejo necessidade de instanciar mais de 1.

Queries seria o mesmo que uma fabrica de PessoaQuery, mas como PessoaQuery e’ um singleton, ele nao pode ser conciderado fabrica.

Quanto ao nome, como disse, o nome pode ser outro, mas o q me atenho aqui sao ha boas praticas…

e gostaria que me disesse onde esta a ma pratica ? e pq eu deveria usar

new PessoaQuery (ou new RepositoryPessoa)

new OutroQuery (ou new RepositoryOutro)

??

quando posso fazer “queries.” e deichar o eclipse me trazer um atalho para a lista com todos os objetos desta categoria ?

nao gosta de fachadas ? paciencia, prefere ter q saber o caminho e o nome de cada Repository ou Query, parabens pra vc, eu prefiro nao ter q me preucupar com isso

Haa e seguindo o padrao fachada… o acesso aos PessoaQuery sao livres, e vc pode nao utilizar o Queries (que e’ apenas o concentrador) e utilizar outro caminho para chegar la

L

Alexandro.Almeida:
Calma que eu não disse que vc não era feliz, apenas usei uma expressão. Nem te conheço, como posso dizer uma coisas destas. :slight_smile:

Eu que eu acho é que a abstração da persistência que o Hibernate, por exemplo, fornece é mais que o suficiente.
Então porque não usar uma classe Repository apenas e implementar a buscas usando o Hibernate diretamente.

Senão eu tenho a impressão se estar usando a abstração da abstração da abstração da …
E ter um repositório de queries, da maneira proposta, não me parece promover o reuso.

O Repositorio e’ reusavel sim… tenho ele sem mudar 1 linha em mais de 10 projetos…

Os objetos utilitarios como HiberanteQuery, as interfaces, Queryable, QueryableList, sao todas reutilizaveis… e tambem os tenho em mais de 10 projetos

A unica parte que nao e’ reutilizavel e’ o EntidadeXQuery obviamente, pois ele guarda a consulta de cada dominio,
e tb ele he trabalho nenhum de fazer, e ele nada mais faz q uma consulta ao hiberante normal, fazendo um DetachedCriteria, e retornando um HibernateQuery(dc).list() por exemplo…

O pacote esta pronto, o reuso e’ grande sim.

e so tenho q criar uma DetachedCriteria, e encapsultar em um HibernateQuery

L

sergiotaborda:

Errado. Primeiro as queries fazem parte da camada de dominio. É um erro comum achar que fazem parte da persistencia, mas não fazem. Elas mudam conforme as regras do dominio e conforme a organização do dominio, logo são da camada de dominio.
Segundo, tudo bem que desassocie as consultas do local onde os objetos estão (DomainStore) , mas o problema aqui é a criação e controle dessas queries, não as queries em si, nem o DomainStore. E é ai que entra o padrão Repository

Não é uma questão de ser legal ou não. É uma questão de ser flexivel, desacoplado, de facil manutenção e testável.

ou eu me expressei mau, ou vc nao entedeu, mas vou explicar novamente…

o que quis dizer e’ que os objetos auxiliares para montagem das consultas, sao parte da camada de persistencia, e por isso eles sao bem definidos e separados do projeto.

Os EntidadeXQuery, realmente sao da camada de dominio, e de persistencia ao mesmo tempo, eles ficam no lemiar, eles fazem realmente limite com as duas camadas.

sua interface externa e’ para camada de dominio, porem sua implementacao usa a camada de persistencia.

S

JPA = Java Persistance API. Você só persiste em banco de dados ?
Supondo que sim, o JPA abstrai a sintaxe nativa do banco ? Não. Ele usa um sub conjunto da SQL que pertende ser universal,mas todos sabemos que isso é furada. é por isso que precisa das nativeQuery. Vc manda o encasuplamento (não era suposto vc saber que está usando um banco) e a portabilidade ( não era suposto saber qual banco usa). Isso é pior que JDBC. Pelo menos em JDBC eu posso criar DAOs para os diferentes bancos.

O problema não é se tem nativeQuery, o problema é o não encapsulamento. O Hibernate é um produto para banco de dados. É um ORM.
A JPA não tem que ser um ORM, mas ela está limitada a ser. Conceitos como Join poderiam ser mais agnosticos, mas eles são desenhados com banco de dados em mente.

A JPA é tecnicamente mais limitada que o Hibernate. Ambos têm o mesmo alvo: banco de dados.
Então a unica coisa que faria usar o JPA seria uma independencia maior (que ele não tem) tanto em termos de modelagem, como em termos de execução. Por exemplo, se o JPA não fosse apenas para banco de dados, valeria a pena. Ou se ele fosse realmente agnóstico. Caso contrário o hibernate já provê as mesmas funcionalidades.

Por outro lado o JPA não faz parte do JEE, logo, vc é tão livre de o escolher como escolher o hibernate ou outro qq ORM.

S
Lavieri:
sergiotaborda:

um lugar onde se guardam e retornam objetos de qualquer tipo é um DomainStore. É por isso que vc consegue criar uma implementação baseada no Hibernate porque ele tb é um DomainStore. Vc está simplesmente desacoplando o conceito da implementação. Mas ao trocar o nome do conceito vc está fazendo um mal a si mesmo.

O repositório é um objeto que cria criterios e os envia ao DomainStore para serem executados.
No seu caso, vc tem uma classe com métodos estáticos que lhe dão a query que precisa e executa em cima do domainStore ( o que vc chama de reposiotorio é na realidade um DomainStore).

A sua arquitetura não tem Repositorios.

Vc não tem [telefone removido] repositorios mas tem [telefone removido] métodos estáticos numa classe. Qual vc acha que é melhor prática ?
Um consulta rápida na internet lhe mostrará que coisas estáticas são evil. A principal razão é que não são testáveis (porque não são "mokáveis").
Aposto que vc não tem testes para essa classe.

hmmm, [telefone removido] métodos estáticos

vc tem certeza que leu parte do codigo que coloquei aqui ?? te desafio a achar 1 metodo estatico sequere, fora o padrao singleton, que vc mesmo sabe que e' boa pratica.

Não. Vc está assumindo coisas que eu nunca disse.
O padrão não pode ser boa prática ou má prática.O uso dele é que pode. Quando vc usa Singleton em java.lang.Runtime é boa prática.
Quando vc usa nos seus XXXQuery é má prática.

Nao ha metodos estaticos, nao ha necessidade deles, meus objetos sao concretos, O que tenho e uma fachada, o que e' outro padrao.
public class Queries {
     public PessoaQuery forPessoa() {
          return PessoaQuery.getInstance();
     }
}

Queries e' uma fachada, serve apenas como concentrador para os varios objetos do tipo Query, como o PessoaQuery.

Get your patterns straight.
Queries não é uma fachada. É um ServiceLocator

esses objetos sao singleton, pq nao vejo necessidade de instanciar mais de 1.

Pois. Esse é um erro comum.
Singleton não é usado para quando vc não quer mais que 1. É para quando vc não pode mais que 1.

veja

public class Queries {
     private PessoaQuery pessoaQuery = new PessoaQuery();

     public PessoaQuery forPessoa() {
          return pessoaQuery;
     }
}

Estou usando singelton ?
Não.

Estou instanciando mais que um ?
Não.

Queries seria o mesmo que uma fabrica de PessoaQuery, mas como PessoaQuery e' um singleton, ele nao pode ser conciderado fabrica.

............

Quanto ao nome, como disse, o nome pode ser outro, mas o q me atenho aqui sao ha boas praticas...

e gostaria que me disesse onde esta a ma pratica ? e pq eu deveria usar

new PessoaQuery (ou new RepositoryPessoa)
new OutroQuery (ou new RepositoryOutro)

Agora que vc explicou melhor, realmente os seus XXXQuery não na realidade repositorios.E é boa prática chamar as coisas com os nomes certos :)

nao gosta de fachadas ? paciencia, prefere ter q saber o caminho e o nome de cada Repository ou Query, parabens pra vc, eu prefiro nao ter q me preucupar com isso

Eu não gosto é de ServiceLocator , nem de métodos estáticos, nem de outras coisas que impedem a felxibilidade e testabilidade.
Vc não precisaria do ".queryOn(repository); " se cada objeto XXXQuery tivesse uma referencia a ele. E isso é facil se eles não forem singleton.
E dessa forma vc consegue estar seu dominio com um domainstore em memoria sem usar banco. Muito mais rápido.
Flexibilidade. Testabilidade.

Haa e seguindo o padrao fachada... o acesso aos PessoaQuery sao livres, e vc pode nao utilizar o Queries (que e' apenas o concentrador) e utilizar outro caminho para chegar la

Vamos pensar que uso o seu Queries. eu tenho que o injetar em todas as actions, mesmo quando sei que cada action só manipula uma certa entidade.
Obviamente eu não vou fazer "new Queres ()" dentro de cada action. eu voi injetar esse objeto.
Portanto, injetar isso ou injetar o próprio XXXQuery , qual é a diferença ? Pelos menos agora eu injeto apenas os XXQuery que preciso e não um God Locator

Enfim, o seu esquema é muito melhor do que é comum por ai. Estou apenas dizendo que poderia ser ainda melhor.

L

o Queries e’ application scoped, ou seja, injeto ele sem problemas so existe 1 no projeto…

eu quase nunca uso o queryOn(repository) … tem um outro metodo query() … so que esse metodo query() apesar de nao precisar do argumento
ele pega o repositorio de uma maneira q so pode ser feita em um app web, ou em um ambiente com threads no mesmo estilo do container web.

pois eu tenho um Interceptador, que guarda a referencia ao repositorio em um ThreadLocal, e resgato ele de la, pois sei, que uma requisicao esta sempre na mesma thread.

nesse ponto eu consigo fazer

List<Pesso> pessoas = queries.forPessoa().listAtivos();

sem usar o queryOn() …

injetar o queries
new Queries(repo).forPessoa().listAtivos();

ou fazer, queries.forPessoas().listaAtivos().queryOn(repo), pra mim tem o mesmo efeito… e eu axo mais bonito a segunda forma, e mais usavel no meu codigo.

vc fala em injetar o Repo dentro do XQuery, para poder usar em testes… mas isso seria o mesmo que nao injetar ele, e usar o metodo queryOn(repo)

Eu realmente nao quero mais de 1 instancia, pelo simples fato de nao precisar de mais de 1, por isso fiz o singleton, o construtor do XQuery e’ privado, portanto nao ha’ como criar ele por ai.

se fosse requerer o repository em sua construcao iria realmente ter q repensar o modelo, e tranformar o Queries em uma fabrica e nao deixar como esta.

Queries.createPessoa(repository).listAtivos();

B

então se o jpa não fosse jpa vc usaria ele? hahhhahahaha

S

bobmoe:
sergiotaborda:

A JPA é tecnicamente mais limitada que o Hibernate. Ambos têm o mesmo alvo: banco de dados.
Então a unica coisa que faria usar o JPA seria uma independencia maior (que ele não tem) tanto em termos de modelagem, como em termos de execução. Por exemplo, se o JPA não fosse apenas para banco de dados, valeria a pena. Ou se ele fosse realmente agnóstico. Caso contrário o hibernate já provê as mesmas funcionalidades.

Por outro lado o JPA não faz parte do JEE, logo, vc é tão livre de o escolher como escolher o hibernate ou outro qq ORM.


então se o jpa não fosse jpa vc usaria ele? hahhhahahaha

Eu não usaria ele a menos que servisse para mais coisas que banco de dados. sim.
É impossível testar um sistema usando JPA sem usar um banco de dados. A Testabilidade do JPA é inexistente. Ao menos com o hibernate dá para encapsular e abstrair a maior parte das coisas.

Se o JPA fosse realmente o Java Persistance API e não o Java ORM API , o mundo seria diferente.

A

sergiotaborda:
bobmoe:
sergiotaborda:

A JPA é tecnicamente mais limitada que o Hibernate. Ambos têm o mesmo alvo: banco de dados.
Então a unica coisa que faria usar o JPA seria uma independencia maior (que ele não tem) tanto em termos de modelagem, como em termos de execução. Por exemplo, se o JPA não fosse apenas para banco de dados, valeria a pena. Ou se ele fosse realmente agnóstico. Caso contrário o hibernate já provê as mesmas funcionalidades.

Por outro lado o JPA não faz parte do JEE, logo, vc é tão livre de o escolher como escolher o hibernate ou outro qq ORM.


então se o jpa não fosse jpa vc usaria ele? hahhhahahaha

Eu não usaria ele a menos que servisse para mais coisas que banco de dados. sim.
É impossível testar um sistema usando JPA sem usar um banco de dados. A Testabilidade do JPA é inexistente. Ao menos com o hibernate dá para encapsular e abstrair a maior parte das coisas.

Se o JPA fosse realmente o Java Persistance API e não o Java ORM API , o mundo seria diferente.

O JCP já tentou, Sérgio, criar uma abstração maior do que banco de dados relacionais através do JDO, mas não funcionou. Justamente pq o mundo corporativo persiste em “banco de dados relacionais”, qualquer abstração maior do que ORM seria uma limitação muito grande. O Hibernate brilhou justamente por causa disso… percebendo que não adianta querer abraçar o mundo em todas as formas de persistencia, Gavin focou seu framework na resolução do problema Objeto para Relacional, e foi feliz. O mesmo ocorreu com a especificação. Não acho isso errado, muito pelo contrário, acho prático …

S

Alessandro Lazarotti:
sergiotaborda:
bobmoe:
sergiotaborda:

A JPA é tecnicamente mais limitada que o Hibernate. Ambos têm o mesmo alvo: banco de dados.
Então a unica coisa que faria usar o JPA seria uma independencia maior (que ele não tem) tanto em termos de modelagem, como em termos de execução. Por exemplo, se o JPA não fosse apenas para banco de dados, valeria a pena. Ou se ele fosse realmente agnóstico. Caso contrário o hibernate já provê as mesmas funcionalidades.

Por outro lado o JPA não faz parte do JEE, logo, vc é tão livre de o escolher como escolher o hibernate ou outro qq ORM.


então se o jpa não fosse jpa vc usaria ele? hahhhahahaha

Eu não usaria ele a menos que servisse para mais coisas que banco de dados. sim.
É impossível testar um sistema usando JPA sem usar um banco de dados. A Testabilidade do JPA é inexistente. Ao menos com o hibernate dá para encapsular e abstrair a maior parte das coisas.

Se o JPA fosse realmente o Java Persistance API e não o Java ORM API , o mundo seria diferente.

O JCP já tentou, Sérgio, criar uma abstração maior do que banco de dados relacionais através do JDO, mas não funcionou.

Isso não totalmente verdade. O problema do JDO é a falta das pessoas o conhecerem. Veja que o Google App Engine usa JDO.
E tem uma implementação JPA em cima de JDO. E isso porque, lá no GAE não ha banco de dados, ha bigtable.
Mas isso tem um preço. Join não funciona. E não funciona porque é um conceito inerente, ou seja, o JPA não faz join, ele delega o join ao banco de dados. A capacidade de abstrair isso é nula.

Cuidado. Esse conceito persiste nas empresas médias e pequenas, não no mundo corporativo como um todo.
Veja que coisas como o bigTable , o movimento NoSQL e os bancos OO estão ganhando terreno.

Não vejo porque seria uma limitação se fosse bem feito. Repare, eu não estou dizendo que vc deveria ter implementações para todos os tipos de coisa
eu estou dizendo que o framework não deveria limitar isso ha partida. Quer fazer join, blz. Se o implementador suportar isso nativamente otimo, senão a implementação do framework deve simular isso. A principal questão é a falta de capacidade de teste, de fazer mocks, etc… É o mesmo problema da EJB 2.x que ainda persiste.

Vou-lhe dar um exemplo real. Eu implemento um sistema usando postgress. Ai eu quero colocar a funcionar no GAE. Não posso fazer isso com simples deploy. Não posso fazer isso sequer apenas substituindo o meu DomainStore, porque ele está vinculado ao conceito de banco relacional. Mas eu quero ter esse trabalho de adaptar a aplicação ao GAE? Não. O que que quero é ter componentes intercambiáveis.

E veja, ele até aceita JPA mas não aceita todo o JPA. Ou seja, duh! obriga vc a fazer um monte de coisas na mão.
Isso já para não falar em testabilidade.

O que JPA lhe dá? Aderência à JEE. Apenas e só. Mas ha muito tempo esta adrencia deixou de ser importante para 90% das aplicações.
Para ser importante vc precisa estar correndo aplicações que só podem funcionar em ambiente JEE.

Aderencia à JEE não significa universalidade, como todos sabemos.
Então, amarrado por amarrado é melhor amarrar-se com quem lhe dá mais capacidade e poderes , no caso o hibernate. e não me entenda mal, eu odeio o hibernate e acho que falta concurrencia, contudo dos dois males ele é o menor.

L

@sergiotarborda

Sergio, mais uma coisa, o meu padrao pode realmente nao ser o padrao repositorio (afinal sua literatura e bem pequena na internete) …

Pode ser o padrao DomainStore…

Mas uma coisa vc nao tem como negar, o nome esta correto, Repository, o padrao pode ate ser outro, mas chamar o lugar onde se guarda as entidades de Repositorio e’ nada alem do obveio, afinal e’ isso que e’ pra mim.

Pode ser que o padrao nao seja este, mas a nomeclatura esta coerente com o que o objeto tem como responsabilidade, que e’ guardar minhas entidades.

A

Cuidado. Esse conceito persiste nas empresas médias e pequenas, não no mundo corporativo como um todo.
Veja que coisas como o bigTable , o movimento NoSQL e os bancos OO estão ganhando terreno.

Médias e pequenas? Você esta dizendo que empresas grandes não utilizam banco relacionais? Sergio, isso não é verdade e esta longe de ser. Não acho interessante expor na internet o nome das empresas que ja participei / participo de projetos que utilizam banco de dados relacionais como seu maior repositório de dados. Contudo posso assegurar que as maiores indústrias do ramo automotivo, telecom, petroquímico e químico utilizam banco de dados relacionais… e não são de fato empresas de pequena e médio porte.

sergiotaborda:
Vou-lhe dar um exemplo real. Eu implemento um sistema usando postgress. Ai eu quero colocar a funcionar no GAE. Não posso fazer isso com simples deploy. Não posso fazer isso sequer apenas substituindo o meu DomainStore, porque ele está vinculado ao conceito de banco relacional. Mas eu quero ter esse trabalho de adaptar a aplicação ao GAE? Não. O que que quero é ter componentes intercambiáveis.

E veja, ele até aceita JPA mas não aceita todo o JPA. Ou seja, duh! obriga vc a fazer um monte de coisas na mão.
Isso já para não falar em testabilidade.

JPA é O"R"M, ponto final. Se o seu sistema é um dos raros que querem persistir em outro meio que não relacional, não é a tecnologia correta a ser utiliza, não vejo onde esta o pecado nisso. Se você tem uma camada de persistência bem definida, melhor ainda, vc pode optar pela implementação ORM ou qualquer outra coisa, inclusive JDO.

Bom mas como já disse, se vc tem uma idéia de arquitetura diferente da minha, discutiriamos até amanhã sem chegar em um consenso. Simplesmente o que é aceitavel pra mim pode não ser pra vc, e vice-versa.

[]s

Criado 16 de março de 2010
Ultima resposta 18 de mar. de 2010
Respostas 57
Participantes 9