最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java的Hibernate框架中用于操作數(shù)據(jù)庫的HQL語句講解

 更新時(shí)間:2016年01月03日 14:56:05   作者:cxshun  
這篇文章主要介紹了Java的Hibernate框架中用于操作數(shù)據(jù)庫的HQL語句講解,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下

 上次我們一起學(xué)習(xí)了用Criteria進(jìn)行相關(guān)的操作,但由于Criteria并不是Hibernate官方推薦的查詢方式,我們也并不多用。現(xiàn)在我們來看一下官方推薦的HQL,一起學(xué)習(xí)一下它的強(qiáng)大。
 說是HQL,也就是Hibernate查詢語句,和SQL有什么區(qū)別呢?一個(gè)字母的區(qū)別,哈哈。
 當(dāng)然不是這樣,HQL和SQL的區(qū)別在于思想的不同,HQL是用面向?qū)ο蟮姆较蜻M(jìn)行查詢,而SQL則是對數(shù)據(jù)庫二維表進(jìn)行查詢,這里包含的是思想的不同。HQL實(shí)際上也是SQL,它由Hibernate幫我們在內(nèi)部進(jìn)行轉(zhuǎn)換,生成SQL。
 1)廢話不多說,我們直接看一下它的強(qiáng)大。
from User 
  這個(gè)代碼很熟悉吧,因?yàn)槲覀冊赟QL中經(jīng)常也用到from 表名,但這里有點(diǎn)不同的是User在這里并不是表名,而是實(shí)體類的名稱,由hibernate幫我們進(jìn)行映射。
 
 聯(lián)想SQL語句,如果我們想查出某個(gè)屬性,并且根據(jù)某個(gè)屬性進(jìn)行條件限制,很簡單可以得到類似語句:

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

  這樣我們就查出了年齡大于20且小于60的User的姓名和年齡。很容易理解。
 SQL語句中的and,or,like,<,>,=等都可以在HQL中進(jìn)行使用。
 需要注意的是當(dāng)我們查詢多個(gè)屬性時(shí),返回的結(jié)果是一個(gè)Object[]數(shù)組,而只有單個(gè)時(shí)是返回Object,這個(gè)需要不同的解析方式,所以在查詢時(shí)需要注意。
 
 2)當(dāng)然,我們前面說了HQL是面向?qū)ο蟮?,而我們這樣做,就不是面向?qū)ο蟮乃枷肓恕N覀儊砀囊幌拢?br />

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

  這樣我們就把查詢到的結(jié)果放到了User對象中,注意,這里調(diào)用的是User的構(gòu)造函數(shù),User類中必須存在接收兩個(gè)參數(shù)的User構(gòu)造函數(shù),否則會(huì)報(bào)錯(cuò),錯(cuò)誤信息大概如下:
Unable to locate appropriate constructor on class [org.hibernate.tutorial.domain8.User] 

  它找不到合適的構(gòu)造函數(shù)。很明白,加上接收對應(yīng)參數(shù)的構(gòu)造函數(shù)就可以了。
 注意,上面當(dāng)我們進(jìn)行查出的時(shí)候并沒有查出相應(yīng)的ID,如果此時(shí)我們調(diào)用saveOrUpdate方法時(shí),它實(shí)際上執(zhí)行的是保存的操作。
 我們看一下測試代碼:
 我在執(zhí)行完上面的查詢語句后,進(jìn)行下面的操作:

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

  這時(shí)Hibernate的語句為:

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

  它新插入一條,而不是更新。
 那么如果我們需要它進(jìn)行更新的時(shí)候就需要把ID一起查出:

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

  記得修改User構(gòu)造方法。
 這時(shí)我們再執(zhí)行我們的測試代碼,此時(shí)會(huì)得到:

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

 
 
 3)我們可以在HQL語句中加上SQL函數(shù):
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中也可以方便地進(jìn)行分組和排序,只要運(yùn)用group by 和 order by 即可,這時(shí)不多講了。
 
 6)我們看到上面都是直接把值寫入進(jìn)行查詢或更新的,如果我們需要?jiǎng)討B(tài)賦值,或賦值的太多,總不能跟JDBC一樣用字符串拼接吧,估計(jì)超過5個(gè),項(xiàng)目組的人都想罵娘了,呵呵。
 還是用著現(xiàn)代化的方法,用占位符來代替然后再設(shè)置具體值。
 我們直接代碼:

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***進(jìn)行設(shè)值的,但不同的是,這里的position從0開始,而PreparedStatement從1開始,這里要特別注意。
 Hibernate2中還有session.find這種方法的,但由于現(xiàn)在用的是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語句當(dāng)中有一個(gè):name這樣的東西,這個(gè)就是引用占位符,我們只需要在后面通過setParameter進(jìn)行設(shè)值即可,注意這里的第一個(gè)參數(shù)需要對應(yīng)HQL語句中的占位符的值。
 當(dāng)然,也許有人又會(huì)說,這個(gè)不面向?qū)ο螅敲次覀兙陀謥砻嫦驅(qū)ο笠话眩?br />  首先弄一個(gè)類來封裝我們查詢的值

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); 

  我們在代碼從直接通過此類進(jìn)行封裝我們需要查詢的值。很面向?qū)ο蟀伞?br /> 有些項(xiàng)目組有一些奇怪的規(guī)定,不許在代碼中出現(xiàn)SQL語句,如果這是一個(gè)規(guī)范,那我見過的我們公司的代碼,全部都是不合格的,杯具的一大堆字符串拼接,看著就郁悶啊。維護(hù)現(xiàn)有項(xiàng)目的人真是傷不起啊。
 代碼中不允許出現(xiàn)SQL語句,這是建議是不錯(cuò),但還是要看場合。我們來看一下Hibernate怎么把HQL配置在映射文件中。
 直接看配置文件:

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

  我們添加了一個(gè)這樣的標(biāo)簽,它表明里面是HQL語句。
 當(dāng)我們需要取到這個(gè)語句時(shí),也只需要在代碼中加入一句:

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

  這樣也就取到了這個(gè)HQL語句。
 
 HQL也可以用SQL中的組合查詢,比如inner join,left outer join,right outer join,full join。
 下面我們來看一下它們的用法:
 還是先看一下實(shí)體類,我們測試中要用到的:

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> 

  大家只要做一下相應(yīng)的包名修改就可以了。
 下面我們正式進(jìn)行測試:
 在測試前我們看一下表中的數(shù)據(jù):
 t_address表數(shù)據(jù)如下:

201613144805709.png (279×87)

t_user表數(shù)據(jù)如下:

201613144821427.png (260×88)

1)首先我們看一下inner join,它在HQL中由inner join fetch,注意這里fetch的意思是指把需要的數(shù)據(jù)取出來,如果不用fetch,我們?nèi)〕鰜淼臄?shù)據(jù)是Object[]數(shù)據(jù)類型的。
 我們先看一下

from TUser usr inner join fetch usr.addresses 

  當(dāng)我們運(yùn)行它時(shí),我們看到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中運(yùn)行可以看到結(jié)果:

201613144900835.png (790×67)

我們可以看到hibernate將它轉(zhuǎn)換成inner join語句,并查出address。
 我們看到結(jié)果中并沒有shun4這個(gè)記錄,因?yàn)樗]有相應(yīng)的address與它記錄。
 
 而我們用inner join而不要fetch時(shí),它打印的語句為:

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 

  似乎語句沒什么區(qū)別,但是當(dāng)我們查出來后它得到的是Object[]數(shù)組類型的,這個(gè)解析的時(shí)候需注意。
 
 當(dāng)我們不用fetch,而只是inner join時(shí),我們需要這樣來解析:

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]); 
  } 
} 

  我們看到打印的結(jié)果:

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 

  它的每個(gè)結(jié)果都是相應(yīng)查出來的對象。
 
 2)left outer join,這個(gè)相當(dāng)于SQL的左連接,我們直接看一下例子:

from TUser usr left outer join fetch usr.addresses 

  當(dāng)我們運(yùn)行上面的語句時(shí),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中進(jìn)行查出,看到:

201613145004498.png (792×91)

我們看到,盡管shun4沒有對應(yīng)的adress,但還是把它查出來,left outer join是指把左邊表的記錄全部查出。
 沒有fetch的情況這里就不講了。
 
 3)接下來我們看一下right outer join,看名字肯定就和left outer join有點(diǎn)關(guān)系的,我們直接看例子就可以明顯看出了。

from TUser usr right outer join fetch usr.addresses 

  我們執(zhí)行它,得到Hibernate輸出的結(jié)果語句為:

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中執(zhí)行后可以看到結(jié)果:

201613145040175.png (794×89)

這里我們可以看到address為Test4的并沒有相應(yīng)的user與它對應(yīng),但它還是并查出來了,right outer join是指把右邊表的記錄全部查出。
 fetch的情況如上,如果不明白可以看一下inner join fetch。
 

相關(guān)文章

  • springBoot使用openfeign來遠(yuǎn)程調(diào)用的實(shí)現(xiàn)

    springBoot使用openfeign來遠(yuǎn)程調(diào)用的實(shí)現(xiàn)

    這篇文章主要介紹了springBoot使用openfeign來遠(yuǎn)程調(diào)用的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java的ThreadPoolExecutor業(yè)務(wù)線程池詳細(xì)解析

    Java的ThreadPoolExecutor業(yè)務(wù)線程池詳細(xì)解析

    這篇文章主要介紹了Java線程池ThreadPoolExecutor詳細(xì)解析,任務(wù)剛開始進(jìn)來的時(shí)候就創(chuàng)建核心線程,核心線程滿了會(huì)把任務(wù)放到阻塞隊(duì)列,阻塞隊(duì)列滿了之后才會(huì)創(chuàng)建空閑線程,達(dá)到最大線程數(shù)之后,再有任務(wù)進(jìn)來,就只能執(zhí)行拒絕策略了,需要的朋友可以參考下
    2024-01-01
  • 基于springboot2集成jpa,創(chuàng)建dao的案例

    基于springboot2集成jpa,創(chuàng)建dao的案例

    這篇文章主要介紹了基于springboot2集成jpa,創(chuàng)建dao的案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • java實(shí)現(xiàn)文件保存到本地的方法

    java實(shí)現(xiàn)文件保存到本地的方法

    本篇文章主要介紹了java實(shí)現(xiàn)文件保存到本地的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-02-02
  • Spring @Conditional注解從源碼層講解

    Spring @Conditional注解從源碼層講解

    @Conditional是Spring4新提供的注解,它的作用是按照一定的條件進(jìn)行判斷,滿足條件給容器注冊bean,這篇文章主要介紹了Spring @Conditional注解示例詳細(xì)講解,需要的朋友可以參考下
    2023-01-01
  • struts2中simple主題下<s:fieldError>標(biāo)簽?zāi)J(rèn)樣式的移除方法

    struts2中simple主題下<s:fieldError>標(biāo)簽?zāi)J(rèn)樣式的移除方法

    這篇文章主要給大家介紹了關(guān)于struts2中simple主題下<s:fieldError>標(biāo)簽?zāi)J(rèn)樣式的移除方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • Spring Boot郵箱鏈接注冊驗(yàn)證及注冊流程

    Spring Boot郵箱鏈接注冊驗(yàn)證及注冊流程

    這篇文章給大家介紹Spring Boot郵箱鏈接注冊驗(yàn)證問題及注冊流程分析,通過實(shí)例代碼給大家分享實(shí)現(xiàn)過程,感興趣的朋友跟隨小編一起看看吧
    2021-07-07
  • Mybatis-Plus實(shí)現(xiàn)自定義SQL具體方法

    Mybatis-Plus實(shí)現(xiàn)自定義SQL具體方法

    Mybatis-Plus是Mybatis的一個(gè)增強(qiáng)工具,它可以優(yōu)化我們的開發(fā)效率,這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)自定義SQL,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • java實(shí)現(xiàn)的新浪微博分享代碼實(shí)例

    java實(shí)現(xiàn)的新浪微博分享代碼實(shí)例

    這篇文章主要介紹了java實(shí)現(xiàn)的新浪微博分享代碼實(shí)例,是通過新浪API獲得授權(quán),然后接受客戶端請求的數(shù)據(jù),第三方應(yīng)用發(fā)送請求消息到微博,喚起微博分享界面,非常的實(shí)用,有相同需要的小伙伴可以參考下。
    2015-03-03
  • 詳解java自定義類

    詳解java自定義類

    這篇文章主要介紹了java自定義類的概念以及用法,文中講解非常詳細(xì),實(shí)例代碼幫助大家更好的理解,感興趣的朋友可以參考下
    2020-06-06

最新評論

崇州市| 天水市| 理塘县| 会理县| 南乐县| 青川县| 古交市| 华蓥市| 呼玛县| 武鸣县| 扎鲁特旗| 新乐市| 吉水县| 且末县| 大埔区| 冷水江市| 灵台县| 湘阴县| 增城市| 图片| 通山县| 法库县| 寿光市| 广东省| 葵青区| 香港| 柯坪县| 东阳市| 图木舒克市| 和静县| 安图县| 汉寿县| 赫章县| 白城市| 裕民县| 西盟| 威信县| 鱼台县| 台湾省| 神木县| 金山区|