Esto com uma duvida aqui pessoal. Estou usando o mentabean do mentaway e gostaria de fazer um join com duas tabelas diferentes. Teria como ?? Da para fazer queries mais complexas com o Mentabean?
Como fazer join usando MentaBean?
23 Respostas
É bem simples. Inevitavelmente vc vai ter que fazer uma query ou outra na mão para a sua aplicação, por razões de performance ou necessidade mesmo.
Se vc quer pegar uma lista de usuários e ordenar por cidade por exemplo, que está numa outra tabela, vc faz assim:
(repare o prefixo "u" que estamos utilizando para a tabela Users. Isso é para diferenciar os campos da tabela Users com os campos da tabela Cidades e fazer assim o join)
StringBuilder sql = new StringBuilder(256);
sql.append("select ").append(session.buildSelect(User.class, "u"));
sql.append(", c.name cidade");
sql.append(" from Users u, Cidades c");
sql.append(" where u.deleted = 'F'");
sql.append(" and u.cidade_id = c.id"); // <======JOIN
sql.append(" order by cidade");
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = conn.prepareStatement(sql.toString());
rset = stmt.executeQuery();
List<User> list = new LinkedList<User>();
while(rset.next()) {
User user = new User();
session.populateBean(rset, user, "u");
list.add(user);
}
return list;
} catch(Exception e) {
throw new RuntimeException(e);
} finally {
// close stmt e rset...
}
Realmente fiquei impressionado com a pouca verbosidade, clareza e abstração do código escrito com o mentabean. Realmente, o Hibernate não tem qualquer chance frente a esse poderoso e inovador framework de ORM.
O método populateBean é praticamente um novo marco na história da ciência da computação, ante ao qual o próprio Knuth se curvaria em respeito.
StringBuilder sql = new StringBuilder(256); sql.append("select ").append(session.buildSelect(User.class, "u")); sql.append(", c.name cidade"); sql.append(" from Users u, Cidades c"); sql.append(" where u.deleted = 'F'"); sql.append(" and u.cidade_id = c.id"); // <======JOIN sql.append(" order by cidade"); PreparedStatement stmt = null; ResultSet rset = null; try { stmt = conn.prepareStatement(sql.toString()); rset = stmt.executeQuery(); List<User> list = new LinkedList<User>(); while(rset.next()) { User user = new User(); session.populateBean(rset, user, "u"); list.add(user); } return list; } catch(Exception e) { throw new RuntimeException(e); } finally { // close stmt e rset... }
Fico feliz que vc tenha ficado impressionado, Eliziario.
Mas só por curiosidade, em que lugar está escrito que isso é a coisa mais inovadora do mundo? E em que lugar está escrito que o MentaBean veio para dominar o mundo e destruir o Hibernate e a Microsoft? E em que lugar está escrito que a única e soberana opção de ORM deve ser o Hibernate, estando iBatis, pBeans, JDO, Angra, MentaBean, etc. destinados a fogueira da inquisição?
Recomendo que vc dê uma lida no FAQ no MentaBean, onde essa e outras questão estão explicadas claramente… ( no final da página: http://www.mentaframework.org/mentabean.jsp)
Teria sido mais proveitoso se vc tivesse postado o exemplo de como fazer isso com o Hibernate…
List cidades = user.getCidades();
List cidades =
user.getCidades();
:lol:
Que maldade…
Acho que vc não entendeu o exemplo, Eliziario.
Estamos pegando uma lista de usuários e ordenando essa lista pela cidade de cada usuário. Como na tabela Users eu guardo apenas o ID da cidade, eu preciso fazer um join com a tabela Cidades para pegar o nome da cidade para só então poder ordená-la.
Isso que vc colocou aí parece que retorna todas as cidades de um usuário…
E ainda poderíamos complicar mais a situação, fazendo um LEFT JOIN pois alguns usuários podem possuir o campo cidade como NULL.
Sérgio,
Essa parte de abertura/fechamento de recursos e o preenchimento da collection poderia ser abstraida pelo framework, não ?
Senão acaba virando um jdbc enrolado…
[]´s
Acho que vc não entendeu tb o exemplo em questão aqui, Maurício.
Dá uma lida na minha resposta ao Eliziario…
Acho que o Hibernate deve fazer isso com tanta facilidade que não compensa vcs perderem o tempo de vcs mostrando aqui pra gente como o Hibernate trataria essas situações…
Veja que o framework aqui está apenas te ajudando a construir uma query. Não estamos tentando bolar um framework que abstrai e generaliza toda e qualquer query, por mais complexa que ela seja.
Concluindo: Não estamos criando uma outra linguagem de queries e sim facilitando a construção de queries SQL. Quem leu o FAQ do MentaBean, viu que lá está escrito que o framework se destina principalmente a quem trabalha com JDBC puro (SQL).
Pois é, falha minha então, aqui vai como se faria no Hibernate:
Acho que vc não entendeu de novo, Maurício.
Leia de novo o tópico que vc verá que o campo nome está em outra tabela (Cidades) daí a necessidade do Join ou Left Join.
Não precisa responder esse tópico não, que eu mesmo vou corrigir o seu exemplo:
from Usuarios u, Cidades c where u.cidade = c.id order by c.name
É isso aí!!! Depois desse exemplo claríssimo eu e todos aqui já estamos aptos a fazer isso com o Hibernate sem qualquer problema! Isso explica claramente como fazer um Join ou left Join com o hibernate para carregar uma lista de usuários ordenada por um campo que está em outra tabela! Obrigado!
Opa Sérgio,
Acho que quem não entendeu agora foi você. A tabela Usuário tem uma chave estrageira pra Cidade, então o objeto usuário deve ter uma referência pra um objeto cidade, certo?
Se ele tem, cidade é apenas uma propriedade de Usuário, então essa consulta é absolutamente válida no Hibernate (e se adicionar um select, em qualquer implementação da JPA), não é necessário fazer um select em cidade também não, os frameworks já fazem isso automaticamente.
Dê uma olhadinha no Hibernate rapaz, você vai ver que vale a pena.
Sergio, a resposta do Mauricio esta certa.
A sua tambem esta, mas nao ha necessidade de fazer aquele produto cartesiano, o hibernate ja faz aquilo.
E a do Eliziario tambem esta certa, no caso da List estiver anotada com @Order(“nome”)
Logo, usando hibernate, a melhor resposta para esse join é
usuario.getCidades();
como disse o Eliziario… e da pra configurar pra ele fazer join ou subselect dependendo dos casos…
Então ok, me desculpe. Como vi apenas uma tabela no from acabei achando que ele não estaria fazendo um join, mas como vc explicou ele se vira para fazer o join por trás dos panos, o que é muito bom mesmo…
Só restou a dúvida de como ele faz isso por trás dos anos?
Ele faz um JOIN ?
Ele faz um LEFT JOIN ? (para aqueles usuários que estiverem com o nome cidade_id = NULL)
Ele faz uma inner query por registro a fim de obter a cidade a partir do cidade_id?
São essas coisas que fazem com que o hibernate seja poderoso, mas não tão simples, pois ele assume um monte de coisas que ou vc sabe ou vc não sabe…
Eu prefiro (e isso é gosto pessoal meu) usar um framework de ORM que faz as tarefas simples e repetitivas como CRUD pra mim e as coisas mais complexas eu mesmo faço com SQL conforme o exemplo em questão…
Não sei se o meu exemplo ficou claro, mas o que estamos procurando aqui é uma lista de Usuários ordernada pelo nome das cidades e NÃO uma lista de cidades.
List<Cidade> cidades = user.getCidades();
Está claramente me retornando uma lista de cidades!
Não tem problema, qualquer uma das consutlas geradas por ele são personalizáveis e você tem o SQL todo também disponível. Se você não achar o modo dele interessante, é só dizer pra ele fazer do seu jeito, ele só assume X ou Y se você não mandar ele fazer de outro jeito e isso é que faz dele uma ferramenta de primeira linha, nem tudo precisa ser feito na unha.
O problema é como personalizar… E como saber o que ele faz por default…
No exemplo que vc colocou, não ficou claro pra mim o que ele assume e como eu poderia, por exemplo, forçar um LEFT JOIN ao invés de um INNER JOIN comum…
Bem, aqui já chegamos no Hibernate em si, mas você poderia simplesmente passar a sua query com o LEFT JOIN (a mesma que foi mostrada no primeiro post) pra ele e ele ia executar e trazer a sua lista de usuários ordenada pelo nome da cidade com o LEFT JOIN.
Pra saber “como” ele faz, é só olhar o comando que ele gerou (ele pode escrever tudo em logs). Mais uma vez, se não for interessante, é só alterar, ele é completamente personalizável.
Eu não sou bom de hql, mas creio que o Sergio queria o seguinte em hibernate:
Abraço
Guilherme
edição: já colocaram esse hql ai em cima…
Apenas uma dúvida:
O exemplo acima não funcionaria apenas se o objeto User possuir um objeto cidade dentro dele?
No meu caso o meu objeto user possui apenas o ID da cidade dentro dele, e não um objeto cidade…
Já percebi que uma vantagem do HQL é te poupar de fazer o join se o join já estiver side previamente configurado, o que é uma boa mesmo… Tenho minhas dúvidas se é melhor o cara aprender Hibernate + HQL ou aprender SQL mesmo (JOIN, LEFT JOIN, UNION, SUBQUERY, etc)
Apenas uma dúvida:O exemplo acima não funcionaria apenas se o objeto User possuir um objeto cidade dentro dele?
No meu caso o meu objeto user possui apenas o ID da cidade dentro dele, e não um objeto cidade…
Aqui já é outra coisa, foi você quem implementou desse jeito, não faz muito sentido pra um Usuario ter uma propriedade que é só um indentificador pra cidade, já que com esse identificador ele não pode fazer absolutamente nada. Mas aí nós já vamos entrar numa discussão que as ferramentas de ORM já mataram a muitos anos…
Olá
Minha opinião:
Há um monte de linguagens específicas por aí baseadas em SQL: HQL, EQL, CQL e outras. As 2 últimas usadas por servidores de eventos.
Todo mundo precisa aprender SQL. Aliás, precisa aprender também noções de álgebra relacional. Caso contrário terá dificuldades de entender e fará bobagens quando usar as ferramentas.
[]s
Luca
Concordo com vc… Se vai ter o id, melhor ter também o objeto Cidade…