… eu não poder/necessitar criar uma entidade para devolver ao serviço ?
Por exemplo, para retornar um produto pelo “id”, ele retornará ao serviço a entidade Produto. Mas e se eu apenas precisar retornar quantos itens foram encontrados (sim, eu uso DAO’s e sem ORM). A grosso modo, na DAO teriamos algo como:
Nesse caso, eu apenas receberia um inteiro contendo o total encontrado. Tendo isto em mente, teria sentido passar essa informação ao repositório ?
Na minha opinião, até faz sentido, porque a DAO é um mundo diferente do mundo do Domínio e suas entidades, mas por outro lado, seria apenas um “passa-repassa” entre DAO-Repositório-Serviço até chegar na Controladora/whatever-you-want o valor “10” por exemplo.
O que os senhores acham a respeito ?
Obs: poderia usar um SELECT * e retornar uma coleção de Produto, mas acho que isto iria gastar processamento desnecessário e ao meu ver, ficaria mais ‘feio’
[quote=hlegius]… eu não poder/necessitar criar uma entidade para devolver ao serviço ?
Por exemplo, para retornar um produto pelo “id”, ele retornará ao serviço a entidade Produto. Mas e se eu apenas precisar retornar quantos itens foram encontrados (sim, eu uso DAO’s e sem ORM). A grosso modo, na DAO teriamos algo como:
Nesse caso, eu apenas receberia um inteiro contendo o total encontrado. Tendo isto em mente, teria sentido passar essa informação ao repositório ?
Na minha opinião, até faz sentido, porque a DAO é um mundo diferente do mundo do Domínio e suas entidades, mas por outro lado, seria apenas um “passa-repassa” entre DAO-Repositório-Serviço até chegar na Controladora/whatever-you-want o valor “10” por exemplo.
O que os senhores acham a respeito ?
[/quote]
A solução é simples embora, tlv, um pouco contra intuitiva.
O repositorio não retorna os objetos de dominio. Ele retorna o resultado da pesquisa. Esse resultado permite encontrar outras informações da pesquisa além dos dados em si.
É semelhante ao objeto ResultSet do JDBC. Vc não obtém objetos “linha” no jdbc.
Então , vc cria um interface Query com os seguintes métodos
[code]interface Query {
public T find();
public Collection<T> list();
public int count();
public boolean isEmpty();
}[/code]
Ai vc implementa como quiser. A implementação padrão é: list retorna a coleção com o resutado e contendo todos os objetos encontrados. find retorna só o primeiro ou null se a pesquisa é vazia. count retorna list().size()
e isEmpty retorna list().isEmpty();
Agora, para um repositorio que use JDBC vc pode implementar as coisas de forma diferente. count , por exemplo, executaria um select diferente que apenas retorna a contagem de itens sem ter que ler os itens ( é isso que vc quer). isEmpty pode executar o mesmo select e comparar se é zero. find pode limitar a procurar ao primeiro item como um Top 1 (SQL SErver ) ou limit (postgres e outros…)
Enfim, com esta interface vc pode escolher como executar o sql porque sabe qual seria mais eficiente.
Outra vantagem do Query é que para repetir a query vc não precisa do repositorio. vc simplesmente invoca o método do query de novo. Se existirem dados novos, eles viram no resultado. Isto é prático especialmente se vc adicionar mais um método list(start, count) que retorna os count seguintes itens a partir de start. Isto é util para paginação.
Se ele retorna os resultados da pesquisa, é correto retornar por ele um “inteiro” contendo o valor da pesquisa do count() correto ?
Entendi. Estive reparando que o Repository serve para buscar dados, trazer list/Collections … não é necessariamente tarefa dele as outras coisas, como adicionar, atualizar, remover ou até mesmo, trazer um valor inteiro - o count().
Então, essa Query object se parece meio com o Repository no aspécto do list()… ou seja, fiquei meio perdido com isto. Um se comunica com o outro, ou cada um faz um papel diferente e nem se encontram no sistema ?
Procurei um pouco sobre QueryObject, mas não descobri se ele é do lado da infra ou se é pertencente ao domínio… acho que meu cerebro deu um nó =)
Ao que reparei, o pessoal usa junto a Criteria que tudo isso junto acaba sendo o embrião de um ORM tipo hibernate…
Se eu falei só besteira, realmente é porque o nó está bem atado =(
Ok, os nomes não ajudaram. QueryObject é um padrão para vc passar os parâmetros para o Repositorio. É o input da pesquisa.
O objeto que me referi é o output da pesquisa o resultado. Não sei se existe um padrão para isto, mas se existisse seria algo como ResultObject.
Um repositorio ideal ( no sentido de ser proximo da ideia ) teria vários métodos de pesquisa, cada um recebendo um objeto com os parametros da pesquisa e retornando um objeto de resultado. (Como exemplo, pense no statement do SQL. Ele recebe um String como parametro e retorna um ResultSet como resposta).
O respositorio realmente devolve uma lista com os objetos que encontrou, mas isso não significa que os métodos retornem List.
Quando vc usa List , List é o seu ResultObject. Repare que vc pode usar a interface de List para implementar as mesma coisa que eu falei que poderia com Query. Afinal List tem métodos para saber o tamanho (size) , se é vazio ( isEmpty) etc… Mas List tem um conjunto de outros métodos que não são relevantes como retainAll e removeAll. Enfim, vc pode implementar uma classe que implementa List e utiliza SQL diferente para implementar cada parte. Mas vc tem pouca flexibilidade.
Do ponto de vista do design é mais correto ter um objeto especifico para ser o seu ResultObject. Este objeto terá uma interface mais simples que List e portanto vai libertá-lo de ter de implementar métodos exotiericos como retainAll().
Mesmo assim, esse objeto terá que permitir acesso aos objetos que são o resultado da pesquisa. Por isso ele tem um método que retorna um collection. Mas o programador pode invocar outros métodos mais uteis e mais eficiente como count();
Ou seja, invocar resultObject.count() é mais rápido que invocar resultObject.list().size() porque por detrás dos panos vc não está carregando nenhum objeto realmente.
Aqui chegamos na questão da implementação. Como seu design segue SoC e o objeto de retorno é uma interface, vc pode simplesmente implementá-lo de várias formas conforme for mais util. O seu conhecimento do backend pode ser utilizado para aumentar a eficiencia e portanto a velocidade e diminuir o consumo de memória.
Vc pode usar vários padrões agora porque o objeto que vc retorna apenas tem que implementar uma interface simples.
(Flyheight e Fastlane são exemplos)
Se vc apenas carrega um List e devolve vc ainda posa fazer isso com o obecjto de retorno.
Por exemplo ( e chamando de QueryResult o objeto que chamei antes de Query para não confundir)
[code]public class Repositorio {
public QueryResult findActive(){
List todosActivos = // … executa o query que retorna um list com o resultado
return new ListQueryResult(todosActivos);
}
}
public class ListQueryResult implements QueryResult{
List all;
ListQueryResult (List all){
this.all = all;
}
public T find (){
return all.isempty ? null : all.get(0);
}
public Collection list(){
return Collections.unmodifiableCollection(all);
}
public int count (){
return all.size();
}
public boolean isEmpty (){
return all.isEmpty();
}
}[/code]
Mas vc poderia implementar assim :
[code]public class Repositorio {
public QueryResult findActive(){
// não executa nada
return new SQLQueryResult (datasource);
}
}
public class SQLQueryResult implements QueryResult{
ResultSet rs = execute("SELECT TOP 1 * FROM table ... ");
if (rs.next){
return readObject(rs);
} else {
return null;
}
}
public Collection list(){
ResultSet rs = execute("SELECT * FROM table ... ");
List all = new ArrayList();
while (rs.next){
all.add(readObject(rs));
}
return Collections.unmodifiableCollection(all);
}
public int count (){
ResultSet rs = execute("SELECT count(1) FROM table … ");
rs.next
return rs.getInt(1);
}
public boolean isEmpty (){
return this.count() == 0;
}
}[/code]
O codigo de invocação do SQL é apenas um exemplo. Vc teria que tratar exceptions, fechar connections , etc…
O DataSource é para obter a coneção (datasource.getConnection()
A ideia é que cada método faz o seu proprio SQL ligeiramente diferente e otimizado para aumentar a eficiencia.
Neste caso, o Repositório “ideal” teria várias pesquisas especializadas. Cada tipo de pesquisa receberia um QueryObject como parametro para podermos filtrar a informação a ser buscada igual você exemplificou, correto ?
Ou seja:
Ah sim, perfeito. Entendi seu ponto de vista. Implementar algo mais “direto” à implementar algo que me obriga a implementar comportamentos que eu não vou ultilizar.
Aqui é o ponto da dúvida. Meu Repository pode muito bem retornar ao meu Serviço um valor “não-collection/list”. Posso muito bem no meu serviço solicitar ao meu repositório que retorne-me o total encontrado, como por exemplo:
public void verificaTotal() {
int totalFound = this.repositorio.count(queryObject);
}
Isso seria equivalente a eu chamar o find().size() só que economizando uma boa memória, pois por detrás teriamos apenas um SELECT COUNT(1)/TOP 1…
Legal, acho que isso desata o nó que esse tópico tinha dado em minha cabeça ! Fico muito grato pela explicação completa que deu.
Agora, aqui você comentou sobre a QueryObject. Eu durante esse final de semana consultei alguns livros e li algumas coisas na rede sobre. Ao que pude entender, o QueryObject é o cara que “tira uma DAO” de jogo. Ele quem roda os SQL’s e devolve os resultados ao Repositório. Ele trabalha junto ao Criteria que é o cara responsável por criar os critérios de busca.
No exemplo que vi no livro, o Repositório do cara recebia uma Criteria como parametro e o Repositório implementava o QueryObject passando a entidade e a criteria por meio de setter injection.
A QueryObject dele montava a sentença SQL, buscava os dados e retornava o ResultSet ao repositório que montava a collection e devolvia assim ao serviço.
O Repositório dele se comporta de maneira bem similar ao que você explicou aqui na thread. Um list simples e “descompromissado” com métodos que não têm utilidade e o count() dele retorna o integer usando o TOP do SQL.
Tal implementação estaria correta ?
Neste caso, o Repositório “ideal” teria várias pesquisas especializadas. Cada tipo de pesquisa receberia um QueryObject como parametro para podermos filtrar a informação a ser buscada igual você exemplificou, correto ?
Ou seja:
[/quote]
Ah! agora entendi o seu ponto. Vc acha que isso são pesquisas especializadas.
Não. São 3 métodos fazendo a mesma pesquisa e retornando informações diferentes dela.
Em um projeto onde vc tivesse a pesquisa “usuáriosAtivos” vc teria
findUsuariosAtivos : List
getFirstusuarioAtivo : usuario
countUsuariosAtivos : int
Para cada pesquisa vc teria 3 metodos. Para N pesqusias vc teria 3N métodos.
Com o outro modelo vc agrupa os métodos em um objeto de retorno. Então vc tem N pesquisas e N métodos.
muito mais simples , não ?
Repare que a frase SQL é a mesma ( porque a pesquisa é a mesma) apenas tem alguns parametros diferentes.
Se vc tiver 3 metodos vc vai escrever a pesquisa 3 vezes. quando a pesquisa mudar é provável que vc esqueça de mudar nos outros 2 métodos. Esse é o real problema da sua opção : manutenabilidade.
For que, vc fizer do seu jeito o seu repositorio vira um DAO. Acho que não isso que vc quer.
Não. Nada disso.
O QueryObject não faz nada. Ele é apenas um conjunto de dados. Um criteria do hibernate é um QueryObject.
O String SQL passado no statement é um QueryObject.
Em um repositorio os parametros são normalmente simples findByID(Integer id) , findByName(String name) , findActive() , findSelledIn (Date start, Date end), etc… quando vc tem muitos parametros vc vai querer combiná-lo num so objeto por exemplo
findSelledIn(Interval intervalo) seria equiavalente ao anterior mas com o start e o end dentro do obejto intervalo, que aqui é o seu QueryObject.
Agora, o QueryObject tende a ser mais complexo. A ideia é vc poder pedir aquelas 4 informações de forma combinada algo assim
Ai vc passa para o método find() e pronto. Bácisamente o seu repositorio começa a ter um só método. Só que isso destroi o repositorio. O objectivo do repositorio é manter e conter a contrução do QueryObject se vc já o opassa construido quer dizer que outro objeto o contruiu - que não o repositorio - e portanto está violando o papel do repositorio. O repositorio torna-se um DAO.
O DAO e o DomainStore funcionam bem com QueryObject. Repare como o QueryObject e SQL são bem semelhantes.
O repositorio recebe parametros mais simples, cria o QueryObject mais complexo que o DAO ou o DomainStore entende e o passa a ele. Depois recebe o resultado e trata esse resultado para ser retornado na estrutura certa.
aposto que isso não era um repositorio e sim um DAO. Pela simples razão que os repositorios não recebem QueryObject complexos ( como já expliquei ) e Criteria é um objeto complexo.
Isso que vc descreveu é o que o um DAO ou um DomainStore faria.
Para um DAO sim. Para um Repositorio não.
A Criteria que foi enviado ao objeto veio de onde ? Foi montada por quem ? Quem escolheu os parametros para ela ?
Em um sistema como Repositorio , seria o repositorios a fazer isso e a invocar esse objeto que vc descreveu.
em um sistema sem Repositorio , básicamente qualquer classe pode invocar o DAO, logo a construção do Criteria está espalhada pelo sistema inteiro. E isso é um problema. Esse é o problema que o repositorio tenta resolver. ele é um cara “acima” do DAO que sabe como criar Criterias , invocar o DAO, e tratar o resultado.
Um Repositório é uma ilusão de coleção de objetos, não alguém que responde à queries. Se você quer saber quantos objetos estão dentro de um repositório provavelmente para o cliente isto é apenas um atributo deste, não o resultado de uma pesquisa.
E antes de partir para QueryObject, algo bem inra-estrutura e fora de DDD, siga a suestão do Evans e faça a dobradinha Specificaction/Repository:
Agora se você ainda não leu o livro eu recomendo que o faça antes de tentar qualquer coisa com Domain-Driven Design. Existem muitas fontes de informação completamente distorcidas por aí.
[quote=“sergiotaborda”]Ah! agora entendi o seu ponto. Vc acha que isso são pesquisas especializadas.
Não. São 3 métodos fazendo a mesma pesquisa e retornando informações diferentes dela.
Em um projeto onde vc tivesse a pesquisa “usuáriosAtivos” vc teria
findUsuariosAtivos : List
getFirstusuarioAtivo : usuario
countUsuariosAtivos : int
Para cada pesquisa vc teria 3 metodos. Para N pesqusias vc teria 3N métodos.
Com o outro modelo vc agrupa os métodos em um objeto de retorno. Então vc tem N pesquisas e N métodos.
muito mais simples , não ?[/quote]
Pera lá então: no seu exemplo temos somente 1 tipo de busca. O que varia são os tipos de retorno. Um Retorna a Collection outro a entidade fora da collection e o outro um número (inteiro) possívelmente.
3 métodos, 1 tipo de busca.
Com isto realmente teriamos muito código duplicado e o problema da manutenabilidade como você disse. Porém, o “outro modelo” que você citou eu não entendi bem como poderia especificar ao método do Repositório que eu quero um getFirstusuarioAtivo ou que eu quero um countUsuariosAtivos.
[quote][code]public class Repositorio {
public QueryResult findActive(){
// não executa nada
return new SQLQueryResult (datasource);
}
}
public class SQLQueryResult implements QueryResult{
ResultSet rs = execute("SELECT TOP 1 * FROM table ... ");
if (rs.next){
return readObject(rs);
} else {
return null;
}
}
public Collection list(){
ResultSet rs = execute("SELECT * FROM table ... ");
List all = new ArrayList();
while (rs.next){
all.add(readObject(rs));
}
return Collections.unmodifiableCollection(all);
}
public int count (){
ResultSet rs = execute("SELECT count(1) FROM table … ");
rs.next
return rs.getInt(1);
}
public boolean isEmpty (){
return this.count() == 0;
}
}[/code][/quote]
Veja, no seu exemplo eu usaria o que para dizer ao findActive() que eu quero chamar o find() que me retornará um TOP 1 por exemplo ?
[quote=“sergiotaborda”]Não. Nada disso.
O QueryObject não faz nada. Ele é apenas um conjunto de dados. Um criteria do hibernate é um QueryObject.
O String SQL passado no statement é um QueryObject.[/quote]
Legal, até aqui eu entendi. No meu pensamento o QueryObject mandava a DAO passear, mas depois da sua explicação eu percebi que ele manda o Repositório passear.
Ao que entendi, o Repositório está para nos servir com Objetos da persistência e agora também evitar um monte de Criteria espalhadas pelas Actions.
Se eu entendi corretamente, uma implementação possível seria:
[code]public class Repositorio {
public Result findAtivos(int porCep) {
// monta a o critério/query object
// passa ao criteria a espeficicação de que queremos por cep
ResultSet rs = usuariosDao.find(Criteria);
// monta o list/collection ou transmite uma info de não localizada
}
}[/code]
Minha Action chamaria o Repositório - nesse caso acho que não precisaria de Serviço:
[code]
public class AlgumacoisaAction {
public static void main(String..) {
Repositorio repo = new Repositorio;
int cep = 12345678;
repo.findAtivos(cep);
}
}[/code]
Dessa forma eu não exibiria a implementação dos critérios de busca, evitaria um monte de Criterio nas Actions.
Eu apenas não entendi como poderia fazer meu Repositório buscar de formas diferentes uma mesma informação, assumindo o exemplo acima…
[code]public class Repositorio {
public Result findAtivos(int porCep) {
// monta a o critério/query object
// passa ao criteria a espeficicação de que queremos por cep
ResultSet rs = usuariosDao.find(Criteria);
// monta o list/collection ou transmite uma info de não localizada
}
public int countAtivos(int porCep) {
//monta o critério
// passa ao critéria o cep
int rs = usuariosDao.count(Criteria);
// retorna isto
}
}[/code]
[code]
public class AlgumacoisaAction {
public static void main(String..) {
Repositorio repo = new Repositorio;
int cep = 12345678;
repo.findAtivos(cep);
int totalAtivoPorCep = repo.countAtivos(cep);
}
}[/code]
Ao que entendi, minha DAO é melhor aproveitada, porém eu teria 3n Métodos no Repositório para n pesquisas especializadas. Justamente o que não é ideal para a manutenabilidade. =(
Pois se eu precisasse fazer uma busca por inativos, eu teria que adicionar no repositório mais 3 métodos. findInativos(); listInativos(); countInativos(); A DAO ficaria com os 3 de sempre, penso.
[quote=“sergiotaborda”]Agora, o QueryObject tende a ser mais complexo. A ideia é vc poder pedir aquelas 4 informações de forma combinada algo assim
QueryObject q = QueryObject.for(Product.class). where(“name”).eq(name). and(“active”).isTrue(). and(“selled”).in(intervalo)
Ai vc passa para o método find() e pronto. Bácisamente o seu repositorio começa a ter um só método. Só que isso destroi o repositorio. O objectivo do repositorio é manter e conter a contrução do QueryObject[/quote]
Entendi. A idéia do QueryObject é não ter aquela chuva de pesquisa no Repositório, logo, isso acaba com a utilidade do mesmo. Entretanto, teremos QueryObject esparramadas em todas Actions. Se precisar alterar algo algum dia, ferrou ! Mas vem cá, o hibernate não trabalha exatamente assim ?
[quote=“sergiotaborda”]aposto que isso não era um repositorio e sim um DAO. Pela simples razão que os repositorios não recebem QueryObject complexos ( como já expliquei ) e Criteria é um objeto complexo.
Isso que vc descreveu é o que o um DAO ou um DomainStore faria. [/quote]
Possivelmente poderia ter sido o usuário utilizando-se da interface selecionou os campos a serem filtrados, porém, novamente a Action que tratou essa informação e criou a criteria.
[quote=“sergiotaborda”]Em um sistema como Repositorio , seria o repositorios a fazer isso e a invocar esse objeto que vc descreveu.
em um sistema sem Repositorio , básicamente qualquer classe pode invocar o DAO, logo a construção do Criteria está espalhada pelo sistema inteiro. E isso é um problema. Esse é o problema que o repositorio tenta resolver. ele é um cara “acima” do DAO que sabe como criar Criterias , invocar o DAO, e tratar o resultado. [/quote]
Isso reforça a idéia: repositório ajuda na manutenção das instruções da Dao.
Isso ! No caso, aliás, no meu caso, geralmente eu preciso de um “count()” para retornar informações para paginações ou/e exibir informações adicionais na interface, como por exemplo: “Vendo X registros de um total de 400”. Em ambos casos, eu precisaria fazer um find() especializado naquele filtro + um count() para saber quantos são os registros todos (sem filtros).
Neste caso Phillip, o que poderia eu fazer ? Implementar o count() no repositório retornando um “Int” ao que entendi, você não é muito a favor, mas eu ainda não consigo ver outra solução…
Seguirei sem dúvidas. Até por que, se eu for criar um queryobject e suas criterias é melhor eu usar algo pronto, como hibernate…
Farei assim que possível. A grande questão é que apenas fora do país tem esse livro disponível, e as lojas nacionais têm um prazo altíssimo para “possível” entrega do mesmo. Isso quebra as pernas =(
[quote=hlegius][quote=“sergiotaborda”]
Para cada pesquisa vc teria 3 metodos. Para N pesqusias vc teria 3N métodos.
Com o outro modelo vc agrupa os métodos em um objeto de retorno. Então vc tem N pesquisas e N métodos.
muito mais simples , não ?[/quote]
Pera lá então: no seu exemplo temos somente 1 tipo de busca. O que varia são os tipos de retorno. Um Retorna a Collection outro a entidade fora da collection e o outro um número (inteiro) possívelmente.
3 métodos, 1 tipo de busca.
Com isto realmente teriamos muito código duplicado e o problema da manutenabilidade como você disse. Porém, o “outro modelo” que você citou eu não entendi bem como poderia especificar ao método do Repositório que eu quero um getFirstusuarioAtivo ou que eu quero um countUsuariosAtivos.
[/quote]
Assim :
QueryResult result = repositorio.findActive();
result.count() // quantos são
result.find() // o primeiro encontrado
result.list() // todos os encontrados
result.isEmpty() // encontrou algum ?
if (result.count()>0){ // ou !result.isEmpty()
for (Produto p : result.list()){
print(p.getName());
}
}
repare que result.count() é mais eficiente que fazer o select todo
vc só irá fazer o select em list() se souber que ha alguma coisa para ler. ( isto é um exemplo, no codigo real vc faz o for e pronto)
Outra forma de usar
// todos os produtos
Collection produtos = repositorio.findAll().list();
// quantos produtos
int quantos = repositorio.findAll().count();
// Todos os produtos ativos
Collection produtos = repositorio.findActive().list();
// quantos produtos foram vendidos o mes passado ?
Month month = Month.current().previous(); // objeto de exemplo só para que se entenda
int quantosVendidos = repositorio.findSelled( month.start(), month.end() ).count();
Repare que um campo só no repositorio não serve. repositorio.count() contao quê ? Isso no máximo informaria o numero total de produtos no repositório mas não o informaria, por exemplo, quantos são ativos ( ou inativos , ou de um certo cliente, ou de uma certa data, etc…). Vc precisa de um count para cada pesquisa. Isso permite automatizar coisas como paginação, por exemplo.
Exactamente isso.
ficaria assim
[code]
public class AlgumacoisaAction {
public static void main(String..) {
Repositorio repo = new Repositorio;
int cep = 12345678;
int totalAtivoPorCep = repo.findAtivos(cep).count();
}
}[/code]
ou
[code]
public class AlgumacoisaAction {
public static void main(String..) {
Repositorio repo = new Repositorio;
int cep = 12345678;
QueryResult qr = repo.findAtivos(cep);
int totalAtivoPorCep = qr.count();
}
}[/code]
O Hibernate funciona exactamente assim porque é uma implementação de DomainStore. Usar QueryObject com DomainStore ou DAO é natural.
Mas isso não significa que vc tem que espalhar as suas Criteria pelos seus Actions. Isso o hibernate não o obriga a fazer.
Vc pode criar um repositorio que chama o hibernate tranqüilamente. (aliás vc deve fazer isso se gosta de codigo mantenivel )
O repositorio que use hibernate é responsável por montar os criteria com base nos parametros e passar ao hibernate.
Implementar um QueryResult baseado no query do hibernate tb é simples, já que o Criteria já implementa os vários métodos diferentes ( ele já otimiza as chamadas da forma que estavamos falando).
Exatamente. esse é o papel principal do repositório. Ele tem outras vantagens, mas todas derivam dai.
Só uma ultima coisa : Repositorios podem - devem - ser usados sempre que vc tiver que escrever pesquisas . Seja SQL puro, Hibernate, JPA , sei la… e em nada usa um repositorio significa que vc esteja utilizando a filosofia DDD ou qualquer uma das suas práticas, vc está simplesmente seguindo o Principio de Separação de Responsabildiade, em particular Encapsulamento, que é uma prática comum do OO.
QueryResult result = repositorio.findActive();
result.count() // quantos são
result.find() // o primeiro encontrado
result.list() // todos os encontrados
result.isEmpty() // encontrou algum ?
if (result.count()>0){ // ou !result.isEmpty()
for (Produto p : result.list()){
print(p.getName());
}
}
repare que result.count() é mais eficiente que fazer o select todo
vc só irá fazer o select em list() se souber que ha alguma coisa para ler. ( isto é um exemplo, no codigo real vc faz o for e pronto)
Outra forma de usar
// todos os produtos
Collection produtos = repositorio.findAll().list();
// quantos produtos
int quantos = repositorio.findAll().count();
// Todos os produtos ativos
Collection produtos = repositorio.findActive().list();
// quantos produtos foram vendidos o mes passado ?
Month month = Month.current().previous(); // objeto de exemplo só para que se entenda
int quantosVendidos = repositorio.findSelled( month.start(), month.end() ).count();
[/quote][/quote]
Ao que entendi, esse findActive() não iria fazer chamada alguma na SQLDao. Apenas montaria o critério de busca. Daí, com o critério pronto, o list() retornaria todos, o count() o SELECT COUNT, o isEmpty() verificaria se não retornou nada e etc… correto ou entendi errado ?
[quote=“sergiotaborda”]O Hibernate funciona exactamente assim porque é uma implementação de DomainStore. Usar QueryObject com DomainStore ou DAO é natural.
Mas isso não significa que vc tem que espalhar as suas Criteria pelos seus Actions. Isso o hibernate não o obriga a fazer.
Vc pode criar um repositorio que chama o hibernate tranqüilamente. (aliás vc deve fazer isso se gosta de codigo mantenivel )
O repositorio que use hibernate é responsável por montar os criteria com base nos parametros e passar ao hibernate.
Implementar um QueryResult baseado no query do hibernate tb é simples, já que o Criteria já implementa os vários métodos diferentes ( ele já otimiza as chamadas da forma que estavamos falando). [/quote]
Legal. Muitos exemplos que eu vi pela rede, trabalha com Active Records. A implementação com Repositório no caso, seria bem similar a implementação com DAO’s comuns, né ? Digo, apenas precisaria mudar, onde eu chamo as daos, eu precisaria transportar os dados para o Hibernate.
Ufa! Acho que estou começando a sacar a idéia =)
O que por si só é excelente.
Abraço e obrigado pela força! Realmente ajudou muito !
Correto. Ele prepara o Criteria , cria um QueryResult para esse critério e retorna.
Internamente o QueryResult utiliza o critério para fazer a pesquisa. Ele pode alterar o critério “ligeiramente” para invocar o resultado que ele quer ( por exemplo o find poderia adicionar o comando criteria.setRange(1,1) ( trás só 1, começando no primeiro) - isso vai se tornar um TOP 1, ou um Limit 1 offset 1 no banco)
Objetos que encapsulam chamadas ao Hibernate e encapsulam a criação de critérios são na realidade Repositorios. É que existe essa moda de os chamar de DAO, mas na realiade DAO é outra coisa. Mas , sim, onde vc tem dao chamando o hibernate vc teria repositorios chamando o hibernate