程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java的Hibernate框架頂用於操作數據庫的HQL語句講授

Java的Hibernate框架頂用於操作數據庫的HQL語句講授

編輯:關於JAVA

Java的Hibernate框架頂用於操作數據庫的HQL語句講授。本站提示廣大學習愛好者:(Java的Hibernate框架頂用於操作數據庫的HQL語句講授)文章只能為提供參考,不一定能成為您想要的結果。以下是Java的Hibernate框架頂用於操作數據庫的HQL語句講授正文


 前次我們一路進修了用Criteria停止相干的操作,但因為Criteria其實不是Hibernate官方推舉的查詢方法,我們也其實不多用。如今我們來看一下官方推舉的HQL,一路進修一下它的壯大。
 說是HQL,也就是Hibernate查詢語句,和SQL有甚麼差別呢?一個字母的差別,哈哈。
 固然不是如許,HQL和SQL的差別在於思惟的分歧,HQL是用面向對象的偏向停止查詢,而SQL則是對數據庫二維表停止查詢,這裡包括的是思惟的分歧。HQL現實上也是SQL,它由Hibernate幫我們在外部停止轉換,生成SQL。
 1)空話不多說,我們直接看一下它的壯大。
from User 
  這個代碼很熟習吧,由於我們在SQL中常常也用到from 表名,但這裡有點分歧的是User在這裡其實不是表名,而是實體類的稱號,由hibernate幫我們停止映照。
 
 聯想SQL語句,假如我們想查出某個屬性,而且依據某個屬性停止前提限制,很簡略可以獲得相似語句:

select usr.name,usr.age from User where usr.age > 20 and usr.age < 60 

  如許我們就查出了年紀年夜於20且小於60的User的姓名和年紀。很輕易懂得。
 SQL語句中的and,or,like,<,>,=等都可以在HQL中停止應用。
 須要留意的是當我們查詢多個屬性時,前往的成果是一個Object[]數組,而只要單個時是前往Object,這個須要分歧的解析方法,所以在查詢時須要留意。
 
 2)固然,我們後面說了HQL是面向對象的,而我們如許做,就不是面向對象的思惟了。我們來改一下:

select new User(usr.name,usr.age) from User usr where usr.age > 20 

  如許我們就把查詢到的成果放到了User對象中,留意,這裡挪用的是User的結構函數,User類中必需存在吸收兩個參數的User結構函數,不然會報錯,毛病信息年夜概以下:
Unable to locate appropriate constructor on class [org.hibernate.tutorial.domain8.User] 

  它找不到適合的結構函數。很明確,加上吸收對應參數的結構函數便可以了。
 留意,下面當我們停止查出的時刻並沒有查出響應的ID,假如此時我們挪用saveOrUpdate辦法時,它現實上履行的是保留的操作。
 我們看一下測試代碼:
 我在履行完下面的查詢語句後,停止上面的操作:

while(iter.hasNext()) { 
 User user = (User)iter.next(); 
 user.setName("sun2"); 
 session.saveOrUpdate(user); 
} 

  這時候Hibernate的語句為:

Hibernate: insert into USER (USER_NAME, age) values (?, ?) 

  它新拔出一條,而不是更新。
 那末假如我們須要它停止更新的時刻就須要把ID一路查出:

select new User(usr.name,usr.age,usr.id) from User usr where usr.age > (select avg(usr.age) from usr) 

  記得修正User結構辦法。
 這時候我們再履行我們的測試代碼,此時會獲得:

Hibernate: update USER set USER_NAME=?, age=? where USER_ID=? 

 
 
 3)我們可以在HQL語句中加上SQL函數:
select usr.name from User usr where usr.age > (select avg(usr.age) from usr) 

  這段HQL查出年紀年夜於均勻年紀的User的name。
 
 4)在Hibernate 3中我們可以很便利地更新和刪除對象,而不用像2中須要先load然後再delete,我們可以直接一條語句弄定:

update User set name='123123' where name='sun33' 

  刪除語句相似:

delete User where name='123123' 

  
 5)Hibernate中也能夠便利地停止分組和排序,只需應用group by 和 order by 便可,這時候不多講了。
 
 6)我們看到下面都是直接把值寫入停止查詢或更新的,假如我們須要靜態賦值,或賦值的太多,總不克不及跟JDBC一樣用字符串拼接吧,估量跨越5個,項目組的人都想罵娘了,呵呵。
 照樣用著古代化的辦法,用占位符來取代然後再設置詳細值。
 我們直接代碼:

Query query = session.createQuery("select new User(usr.name,usr.age,usr.id) from User usr where usr.name=?"); 
query.setString(0,"shun"); 

  我們看到這類辦法跟我們直接用的PreparedStatement相似,都是經由過程set***停止設值的,但分歧的是,這裡的position從0開端,而PreparedStatement從1開端,這裡要特殊留意。
 Hibernate2中還有session.find這類辦法的,但因為如今用的是3其實不多說它了。
 下面我們用的這類占位符叫次序占位符,別的有一種叫援用占位符的,我們來看一下:

Query query = session.createQuery("select new User(usr.name,usr.age,usr.id) from User usr where usr.name=:name"); 
query.setParameter("name","shun"); 

  看到我們HQL語句傍邊有一個:name如許的器械,這個就是援用占位符,我們只須要在前面經由過程setParameter停止設值便可,留意這裡的第一個參數須要對應HQL語句中的占位符的值。
 固然,或許有人又會說,這個不面向對象,那末我們就又來面向對象一把:
 起首弄一個類來封裝我們查詢的值

public class UserQuery { 
 
 private String name; 
 private int age; 
  //省略Get/Set辦法 
  
} 
Query query = session.createQuery("select new User(usr.name,usr.age,usr.id) from User usr where usr.name=:name"); 
 
UserQuery uq = new UserQuery(); 
uq.setName("shun"); 
   
query.setProperties(uq); 

  我們在代碼從直接經由過程此類停止封裝我們須要查詢的值。很面向對象吧。
有些項目組有一些奇異的劃定,不准在代碼中湧現SQL語句,假如這是一個標准,那我見過的我們公司的代碼,全體都是不及格的,杯具的一年夜堆字符串拼接,看著就愁悶啊。保護現有項目標人真是傷不起啊。
 代碼中不許可湧現SQL語句,這是建議是不錯,但照樣要看場所。我們來看一下Hibernate怎樣把HQL設置裝備擺設在映照文件中。
 直接看設置裝備擺設文件:

<query name="queryByName"> 
 <![CDATA[ 
  from User usr where usr.name=:name 
 ]]> 
</query> 

  我們添加了一個如許的標簽,它注解外面是HQL語句。
 當我們須要取到這個語句時,也只須要在代碼中參加一句:

Query query = session.getNamedQuery("queryByName"); 

  如許也就取到了這個HQL語句。
 
 HQL也能夠用SQL中的組合查詢,好比inner join,left outer join,right outer join,full join。
 上面我們來看一下它們的用法:
 照樣先看一下實體類,我們測試中要用到的:

public class TUser implements Serializable{ 
 
 private static final long serialVersionUID = 1L; 
 
 private int id; 
 private int age; 
 private String name; 
 private Set<Address> addresses = new HashSet<Address>(); 
  //省略Get/Set辦法 
} 
public class Address implements Serializable{ 
 
 private static final long serialVersionUID = 1L; 
 
 private int id; 
 private String address; 
 private TUser user; 
  //省略Get/Set辦法 
} 

  上面我們看一下映照文件:

<hibernate-mapping package="org.hibernate.tutorial.domain6"> 
 <class name="TUser" table="t_user" dynamic-insert="true" dynamic-update="true"> 
  <id name="id" column="id"> 
   <generator class="native" /> 
  </id> 
  <property name="name" type="java.lang.String" column="name"/> 
  <property name="age" type="java.lang.Integer" column="age"/> 
  <set name="addresses" cascade="all" table="t_address" inverse="true"> 
   <key column="user_id" /> 
   <one-to-many class="Address"/> 
  </set> 
 </class> 
</hibernate-mapping> 
<hibernate-mapping package="org.hibernate.tutorial.domain6"> 
 <class name="Address" table="t_address" dynamic-insert="false" dynamic-update="false"> 
  <id name="id" column="id" type="java.lang.Integer"> 
   <generator class="native" /> 
  </id> 
  <property name="address" column="address" type="java.lang.String" /> 
  <many-to-one name="user" class="TUser" 
   column="user_id" not-null="true"></many-to-one> 
 </class> 
</hibernate-mapping> 

  年夜家只需做一下響應的包名修正便可以了。
 上面我們正式停止測試:
 在測試前我們看一下表中的數據:
 t_address表數據以下:

t_user表數據以下:

1)起首我們看一下inner join,它在HQL中由inner join fetch,留意這裡fetch的意思是指把須要的數據掏出來,假如不消fetch,我們掏出來的數據是Object[]數據類型的。
 我們先看一下

from TUser usr inner join fetch usr.addresses 

  當我們運轉它時,我們看到hibernate輸入為:

Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.user_id as user3_0__, addresses1_.id as id0__ from t_user tuser0_ inner join t_address addresses1_ on tuser0_.id=addresses1_.user_id 

  我們在mysql中運轉可以看到成果:

我們可以看到hibernate將它轉換成inner join語句,並查出address。
 我們看到成果中並沒有shun4這個記載,由於他並沒有響應的address與它記載。
 
 而我們用inner join而不要fetch時,它打印的語句為:

Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_ from t_user tuser0_ inner join t_address addresses1_ on tuser0_.id=addresses1_.user_id 

  仿佛語句沒甚麼差別,然則當我們查出來後它獲得的是Object[]數組類型的,這個解析的時刻需留意。
 
 當我們不消fetch,而只是inner join時,我們須要如許來解析:

Query query = session.createQuery("from TUser usr inner join usr.addresses"); 
 
List list = query.list(); 
Iterator iter = list.iterator(); 
   
while(iter.hasNext()) { 
  Object[] results = (Object[])iter.next(); 
  for (int i = 0; i < results.length; i ++ ) { 
  System.out.println(results[i]); 
  } 
} 

  我們看到打印的成果:

org.hibernate.tutorial.domain6.TUser@16925b0 
org.hibernate.tutorial.domain6.Address@914f6a 
org.hibernate.tutorial.domain6.TUser@787d6a 
org.hibernate.tutorial.domain6.Address@71dc3d 
org.hibernate.tutorial.domain6.TUser@1326484 
org.hibernate.tutorial.domain6.Address@16546ef 

  它的每一個成果都是響應查出來的對象。
 
 2)left outer join,這個相當於SQL的左銜接,我們直接看一下例子:

from TUser usr left outer join fetch usr.addresses 

  當我們運轉下面的語句時,hibernate打印出:

Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.user_id as user3_0__, addresses1_.id as id0__ from t_user tuser0_ left outer join t_address addresses1_ on tuser0_.id=addresses1_.user_id 

  我們在mysql中停止查出,看到:

我們看到,雖然shun4沒有對應的adress,但照樣把它查出來,left outer join是指把右邊表的記載全體查出。
 沒有fetch的情形這裡就不講了。
 
 3)接上去我們看一下right outer join,看名字確定就和left outer join有點關系的,我們直接看例子便可以顯著看出了。

from TUser usr right outer join fetch usr.addresses 

  我們履行它,獲得Hibernate輸入的成果語句為:

Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.user_id as user3_0__, addresses1_.id as id0__ from t_user tuser0_ right outer join t_address addresses1_ on tuser0_.id=addresses1_.user_id 

  我們在mysql中履行後可以看到成果:

這裡我們可以看到address為Test4的並沒有響應的user與它對應,但它照樣並查出來了,right outer join是指把左邊表的記載全體查出。
 fetch的情形如上,假如不明確可以看一下inner join fetch。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved