A última vez que aprendemos a usar os critérios para realizar operações relacionadas juntas, mas como os critérios não são o método de consulta oficialmente recomendado pelo Hibernate, não o usamos muito. Agora, vamos dar uma olhada no HQL oficialmente recomendado e aprender o quão poderoso ele é juntos.
Qual é a diferença entre o HQL ou a declaração de consulta Hibernate e o SQL? A diferença entre uma letra, haha.
Claro que esse não é o caso. A diferença entre HQL e SQL está nas diferentes idéias. O HQL usa uma direção orientada a objetos para consultar, enquanto o SQL usa uma consulta para tabelas de banco de dados bidimensionais. O que está incluído aqui é a diferença de idéias. O HQL é na verdade o SQL e é feito pelo Hibernate para converter e gerar o SQL internamente.
1) Sem mais delongas, vamos dar uma olhada em seu poder.
do usuário
Esse código é muito familiar, porque geralmente usamos os nomes de tabela no SQL, mas a diferença aqui é que o usuário não é o nome da tabela aqui, mas o nome da classe de entidade e o Hibernate nos ajuda a mapear.
As declarações SQL associadas, se quisermos encontrar um determinado atributo e limitá -lo condicionalmente de acordo com um determinado atributo, podemos obter uma declaração semelhante:
selecione usr.name, usr.age do usuário onde usr.age> 20 e usr.age <60
Dessa forma, encontramos os nomes e idades de usuários com mais de 20 anos ou menos de 60 anos. É fácil de entender.
As e, ou, como, <,>, = e assim por diante nas instruções SQL podem ser usadas no HQL.
Deve -se notar que, quando consultarmos vários atributos, o resultado retornado é uma matriz de objeto [] e, quando apenas um único, o objeto é retornado. Isso requer diferentes métodos de análise, portanto, você precisa prestar atenção ao consultar.
2) É claro que dissemos anteriormente que o HQL é orientado a objetos e, se fizermos isso, não é uma idéia orientada a objetos. Vamos mudar isso:
Selecione novo usuário (usr.name, usr.age) no usuário usr where usr.age> 20Dessa forma, colocamos o resultado da consulta no objeto do usuário. Observe que o construtor do usuário é chamado aqui. Deve haver um construtor de usuário que receba dois parâmetros na classe de usuário, caso contrário, um erro será relatado. A mensagem de erro é aproximadamente a seguinte:
Não é possível localizar o construtor apropriado na classe [org.hibernate.tutorial.domain8.user]
Não pode encontrar um construtor adequado. É muito claro que basta adicionar o construtor que recebe os parâmetros correspondentes.
Observe que, quando verificamos o ID correspondente, não descobrimos. Se chamarmos o método SaveorUpdate no momento, ele realmente executou a operação salva.
Vamos dar uma olhada no código de teste:
Depois de executar a declaração de consulta acima, execute as seguintes operações:
while (iter.hasNext ()) {usuário do usuário = (usuário) iter.Next (); user.setName ("Sun2"); session.SaveorUpdate (usuário); } Neste momento, a declaração de hibernato é:
Hibernate: Insira no usuário (user_name, idade) valores (?,?)
Ele insere um novo, não uma atualização.
Então, se precisarmos atualizar, precisamos descobrir o ID juntos:
Selecione novo usuário (usr.name, usr.age, usr.id) do usuário usr where usr.age> (selecione avg (usr.age) de USR)
Lembre -se de modificar o construtor do usuário.
Neste momento, executamos nosso código de teste novamente e você receberá:
Hibernate: Atualize o usuário do usuário user_name =?, Idade =? onde user_id =?
Selecione usr.name do usuário usr onde usr.age> (selecione avg (usr.age) de USR)
Este HQL detecta o nome do usuário mais antigo que a idade média.
4) No Hibernate 3, podemos atualizar e excluir facilmente objetos, sem ter que carregar primeiro e depois excluir em 2. Podemos fazê -lo diretamente em uma declaração:
Atualizar nome do conjunto de usuários = '123123' onde o nome = 'Sun33'
Excluir declarações são semelhantes:
Exclua o usuário onde nome = '123123'
5) Também é fácil agrupar e classificar em Hibernate. Basta usar o grupo e encomendar, e eu não vou falar mais sobre isso neste momento.
6) Vemos que o acima foi escrito diretamente para consultar ou atualizar. Se precisarmos de atribuição dinâmica ou há muitas tarefas, não podemos consumir strings como o JDBC. Estima -se que existem mais de 5, e todos na equipe do projeto querem me repreender, haha.
É melhor usar um método moderno, usar espaços reservados e definir valores específicos.
Nosso código direto:
Query Query = session.createquery ("Selecione novo usuário (usr.name, usr.age, usr.id) do usuário usr onde usr.name =?"); Query.SetString (0, "Shun"); Vemos que esse método é semelhante ao estatuto preparado que usamos diretamente. Ele é definido através do conjunto ***, mas a diferença é que a posição aqui começa a partir de 0, enquanto o estatuto preparado começa a partir de 1, então preste atenção especial aqui.
Há também um método de sessão.Find no Hibernate2, mas como uso 3 agora, não vou dizer muito sobre isso.
O espaço reservado que usamos acima é chamado de espaço reservado para ordem e há outro chamado espaço reservado de referência. Vamos dar uma olhada:
Query Query = session.createquery ("Selecione novo usuário (usr.name, usr.age, usr.id) do usuário usr onde usr.name =: name"); query.setParameter ("Nome", "Shun"); Vi que há uma coisa como: nome em nossa declaração HQL. Este é um espaço reservado para referência. Precisamos definir apenas o valor através do setParameter mais tarde. Observe que o primeiro parâmetro aqui precisa corresponder ao valor do espaço reservado na instrução HQL.
Obviamente, algumas pessoas podem dizer que isso não é orientado a objetos, então vamos para orientados a objetos novamente:
Primeiro, crie uma classe para encapsular o valor que consultamos
classe pública userQuery {private string name; private Int Age; // omita o método get/set} Query Query = session.createQuery ("Selecione novo usuário (usr.name, usr.age, usr.id) do usuário usr where usr.name =: name"); UserQuery uq = new userQuery (); uq.setName ("Shun"); query.setProperties (UQ); Encapsamos os valores que precisamos consultar diretamente através desta classe. Muito orientado a objetos.
Algumas equipes de projeto têm alguns regulamentos estranhos que as instruções SQL não podem aparecer no código. Se isso é uma especificação, todos os códigos da nossa empresa que eu vi são não qualificados. Muitos emenda de cordas no copo fazem com que pareça deprimido. É realmente difícil se machucar manter os projetos existentes.
As instruções SQL não são permitidas no código. Esta é uma boa sugestão, mas depende da ocasião. Vamos dar uma olhada em como o Hibernate configura o HQL no mapeamento de arquivos.
Olhe diretamente para o arquivo de configuração:
<Query name = "QuerybyName"> <! [CDATA [do usuário usr onde usr.name =: name]]> </query>
Adicionamos uma tag como essa, que indica que é uma instrução HQL.
Quando precisamos obter esta declaração, precisamos adicionar apenas uma frase ao código:
Query Query = session.getNamedQuery ("QuerybyName"); Dessa forma, a instrução HQL é obtida.
O HQL também pode ser consultado usando combinações no SQL, como junção interna, junção externa esquerda, junção externa direita, junção completa.
Vamos dar uma olhada no uso deles:
Vamos dar uma olhada na aula de entidade primeiro, o que precisamos usar em nossos testes:
public class Tusser implementa serializável {private estático final serialversionuid = 1L; private int id; private Int Age; nome de string privado; Conjunto privado <endereço> endereços = novo hashset <deedent> (); // omita método de get/set} endereço público implementa serializável {private estático final serialversionuid = 1L; private int id; endereço de string privado; Usuário privado de Divocante; // omita o método Get/Set} Vamos dar uma olhada no arquivo de mapeamento:
<hibernate-mapping package = "org.hibernate.tutorial.domain6"> <classe name = "tuser" tabela = "t_user" dinâmico-insert = "true" dinâmico update = "true"> <id name = "id" "JAV" JAV = "id"> <generator/> </id> <weead) name = "idade" tipo = "java.lang.integer" column = "idade"/> <set name = "endereços" cascade = "all" tabela = "t_address" inverse = "true"> <key column = "userate_id"/> <hene-to-many/> </set> </class> </hib-mapping "/> package = "org.hibernate.tutorial.domain6"> <classe name = "endereço" tabela = "t_address" dinâmico-insert = "false" dinâmico update = "false" dynamic update = "false" dinâmico update = "id" type = "java.lang.integger"> <generator /> type = "java.lang.string"/> <many-to-one name = "user" column = "user_id" não-null = "true"> </anyst-to-one> </s class> </hibernate-mapping>
Você só precisa modificar o nome do pacote correspondente.
Vamos realizar testes formais:
Antes de testar, vejamos os dados na tabela:
Os dados da tabela T_Address são os seguintes:
Os dados da tabela T_USER são os seguintes:
1) Primeiro, vamos dar uma olhada na junção interna, que é buscada no HQL por ingressos internos. Observe que o significado de buscar aqui é buscar os dados necessários. Se a busca não for usada, os dados que buscamos são do tipo de dados do objeto [].
Vamos dar uma olhada primeiro
do Diretor USR INTERNO JUNCE FETCH USR.ADDRESSESSESSES
Quando o executamos, vemos que a saída do hibernato é:
Hibernate: selecione TUSER0_.ID AS ID1_0_, ENDERETES1_.ID AS ID0_1_, TUSER0_.NAME COMO NAME t_address endereços1_ no tuser0_.id = endereços1_.user_id
Podemos ver os resultados ao executar no MySQL:
Podemos ver que o Hibernate o converte em uma declaração de junção interna e descobre o endereço.
Vemos que não há registro de Shun4 no resultado, porque ele não possui o endereço e o registro correspondentes.
Quando usamos a junção interna em vez de buscar, a declaração que imprime é:
Hibernate: selecione TUSER0_.ID AS ID1_0_, ENDERETES1_.ID AS ID0_1_, TUSER0_.NAME COMO NAME tuser0_.id = endereços1_.user_id
Parece que a afirmação não é diferente, mas quando descobrimos, ela recebe um tipo de matriz objeto [], então você precisa prestar atenção a essa análise.
Quando não usamos o Fetch, mas apenas o interior de junho, precisamos analisar assim:
Query Query = session.CreateQuery ("do Tuser USR Inner Junção usr.addresses"); Lista da lista = query.list (); Iterator iter = list.iterator (); while (iter.hasnext ()) {object [] Results = (object []) iter.Next (); for (int i = 0; i <resultados.Length; i ++) {System.out.println (resultados [i]); }} Vemos o resultado da impressão:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
Cada um de seus resultados é o objeto correspondente.
2) Junção externa esquerda, isso é equivalente à conexão esquerda do SQL. Vamos dar uma olhada no exemplo diretamente:
Do Divulador Usr, a junção externa esquerda, busque usr.addresses
Quando executamos a declaração acima, o Hibernate imprime:
Hibernate: selecione TUSER0_.ID AS ID1_0_, ENDEREES1_.ID AS ID0_1_, TUSER0_.NAME COMO NAME Junte -se t_address endereços1_ no tuser0_.id = endereços1_.user_id
Verificamos no MySQL e vimos:
Vemos que, embora o Shun4 não tenha um endereço correspondente, ele ainda é descoberto. A junção externa esquerda refere -se a descobrir todos os registros na tabela esquerda.
Não vou falar sobre a situação sem buscar aqui.
3) Em seguida, vamos dar uma olhada na junção externa certa. A julgar pelo nome, ele deve estar relacionado à junção externa esquerda. Podemos vê -lo claramente olhando diretamente para os exemplos.
do Diretor Diretor Direito, Junção Externa Fetch Fetch usr.Adresses
Nós o executamos e obtemos a saída de declaração de resultado do Hibernate é:
Hibernate: selecione TUSER0_.ID AS ID1_0_, ENDEREES1_.ID AS ID0_1_, TUSER0_.NAME COMO NAME Junte -se t_address endereços1_ no tuser0_.id = endereços1_.user_idPodemos ver os resultados depois de executar no MySQL:
Aqui podemos ver que o endereço é test4 e não possui o usuário correspondente correspondente a ele, mas ainda é encontrado. A junção externa direita refere -se a descobrir todos os registros na tabela certa.
A situação de busca é como acima. Se você não entende, pode dar uma olhada no INNER JONCE FETCH.