日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

EJB3.0 JPQL

發(fā)布時(shí)間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EJB3.0 JPQL 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?來(lái)源 :http://blog.csdn.net/bryanliu1982/archive/2009/04/17/4087254.aspx

 

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData("text"); if (text && text.length>300) { text = text + "/r/n/n本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:" + location.href; clipboardData.setData("text", text); } }, 100); } } </script> <script class="blogstory">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>

JPQL就是一種查詢語(yǔ)言,具有與 SQL 相類似的特征, JPQL 是完全面向?qū)ο蟮?#xff0c;具備繼承、多態(tài)和關(guān)聯(lián)等特性,和hibernate HQL很相似。 查詢語(yǔ)句的參數(shù) JPQL 語(yǔ)句支持兩種方式的參數(shù)定義方式 : 命名參數(shù)和位置參數(shù) 。在同一個(gè)查詢語(yǔ)句中只允許使用一種參數(shù)定義方式。 命令參數(shù)的格式為:“ : + 參數(shù)名” 例: Query query = em.createQuery("select p from Person p where p.personid=:Id "); query.setParameter("Id",new Integer(1)); 位置參數(shù)的格式為“ ?+ 位置編號(hào)” 例: Query query = em.createQuery("select p from Person p where p.personid=?1 "); query.setParameter(1,new Integer(1)); 如果你需要傳遞 java.util.Date java.util.Calendar 參數(shù)進(jìn)一個(gè)參數(shù)查詢 你需要使用一個(gè)特殊的 setParameter() 方法 ,相關(guān)的 setParameter 方法定義如下: public interface Query { // 命名參數(shù)查詢時(shí)使用,參數(shù)類型為 java.util.Date Query setParameter(String name, java.util.Date value, TemporalType temporalType); // 命名參數(shù)查詢時(shí)使用,參數(shù)類型為 java.util.Calendar Query setParameter(String name, Calendar value, TemporalType temporalType); // 位置參數(shù)查詢時(shí)使用,參數(shù)類型為 java.util.Date Query setParameter(int position, Date value, TemporalType temporalType); // 位置參數(shù)查詢時(shí)使用,參數(shù)類型為 java.util.Calendar Query setParameter(int position, Calendar value, TemporalType temporalType); } 因?yàn)橐粋€(gè) Date Calendar 對(duì)象能夠描述一個(gè)真實(shí)的日期、時(shí)間或時(shí)間戳 . 所以我們需要告訴 Query 對(duì)象怎么使用這些參數(shù),我們 javax.persistence.TemporalType 作為參數(shù)傳遞進(jìn) setParameter 方法,告訴查詢接口在轉(zhuǎn)換 java.util.Date java.util.Calendar 參數(shù)到本地 SQL 時(shí)使用什么數(shù)據(jù)庫(kù)類型 下面通過(guò)實(shí)例來(lái)學(xué)習(xí)JPQL語(yǔ)句,例子的entity Bean Person, Order, OrderItem 他們之間的關(guān)系是:一個(gè) Person 有多個(gè) Order, 一個(gè) Order 有多個(gè) OrderItem JPQL語(yǔ)句的大小寫敏感性:除了 Java 類和屬性名稱外,查詢都是大小寫不敏感的 。所以, SeLeCT sELEct 以及 SELECT 相同的,但是 com.foshanshop.ejb3.bean.Person com.foshanshop.ejb3.bean.PERSon 是不同的, person.name person.NAME 也是不同的。 命名查詢 可以在實(shí)體 bean 通過(guò) @NamedQuery or @NamedQueries 預(yù)先定義一個(gè)或多個(gè)查詢語(yǔ)句,減少每次因書寫錯(cuò)誤而引起的 BUG 。通常把經(jīng)常使用的查詢語(yǔ)句定義成命名查詢 定義單個(gè)命名查詢: @NamedQuery (name= "getPerson" , query= "FROM Person WHERE personid=?1" ) @Entity public class Person implements Serializable{ 如果要定義多個(gè)命名查詢,應(yīng)在@javax.persistence.NamedQueries里定義 @NamedQuery @NamedQueries ({ @NamedQuery (name= "getPerson" , query= "FROM Person WHERE personid=?1" ), @NamedQuery (name= "getPersonList" , query= "FROM Person WHERE age>?1" ) }) @Entity public class Person implements Serializable{ 當(dāng)命名查詢定義好了之后,我們就可以通過(guò)名稱執(zhí)行其查詢。代碼如下: Query query = em . createNamedQuery("getPerson") ; query.setParameter(1, 1); 排序 (order by) "ASC" "DESC" 分別為升序和降序, JPQL 中默認(rèn)為 asc 升序 例: // 先按年齡降序排序,然后按出生日期升序排序 Query query = em.createQuery("select p from Person p order by p.age desc, p.birthday asc "); 查詢部分屬性 通常來(lái)說(shuō),都是針對(duì) Entity 類的查詢,返回的也是被查詢的 Entity 類的實(shí)體。J P QL 也允許我們直接查詢返回我們需要的屬性,而不是返回整個(gè) Entity 在一些 Entity 中屬性特別多的情況,這樣的查詢可以提高性能 例: // 查詢我們感興趣的屬性 ( ) Query query=em.createQuery("select p.personid, p.name from Person p order by p.personid desc "); // 集合中的元素不再是 Person, 而是一個(gè) Object[] 對(duì)象數(shù)組 List result = query.getResultList(); if (result!=null){ Iterator iterator = result.iterator(); while( iterator.hasNext() ){ Object[] row = ( Object[]) iterator.next(); int personid = Integer.parseInt(row[0].toString()); String PersonName = row[1].toString(); 。。。。 } } 查詢中使用構(gòu)造器 (Constructor) JPQL 支持將查詢的屬性結(jié)果直接作為一個(gè) java class 的構(gòu)造器參數(shù),并產(chǎn)生實(shí)體作為結(jié)果返回 例如上面的例子只獲取person entity bean的name and personid屬性,我們不希望返回的集合的元素是object[],而希望用一個(gè)類來(lái)包裝它。就要用到使用構(gòu)造器 例: public class SimplePerson { ?private Integer personid; private String name ; ?? 。。。。 public SimplePerson() { } public SimplePerson(Integer personid, String name) { this . name = name; this . personid = personid; } } 查詢代碼為: // 我們把需要的兩個(gè)屬性作為 SimplePerson 的構(gòu)造器參數(shù),并使用 new 函數(shù)。 Query query = em.createQuery(" select new com.foshanshop.ejb3.bean.SimplePerson(p. personid, p.name) from Person p order by p.personid desc "); // 集合中的元素是 SimplePerson 對(duì)象 List result = query.getResultList(); if (result!=null){ Iterator iterator = result.iterator(); while( iterator.hasNext() ){ SimplePerson simpleperson = (SimplePerson) iterator.next(); 。。。。 } } 聚合查詢 (Aggregation) JPQL 支持的聚合函數(shù) 包括: 1. AVG() 2. SUM() 3. COUNT() 返回類型為 Long ,注意 count(*) 語(yǔ)法在 hibernate 中可用,但在 toplink 其它產(chǎn)品中并不可用 4. MAX() 5. MIN() 例: // 獲取最大年齡 Query query = em.createQuery("select max(p.age) from Person p"); Object result = query.getSingleResult(); String maxAge = result.toString(); // 獲取平均年齡 query = em.createQuery("select avg(p.age) from Person p"); // 獲取最小年齡 query = em.createQuery("select min(p.age) from Person p"); // 獲取總?cè)藬?shù) query = em.createQuery("select count(p) from Person p"); // 獲取年齡總和 query = em.createQuery("select sum(p.age) from Person p"); 如果聚合函數(shù)不是 select...from 的唯一一個(gè)返回列,需要使用 "GROUP BY" 語(yǔ)句 "GROUP BY" 應(yīng)該包含 select 語(yǔ)句中除了聚合函數(shù)外的所有屬性。 例: // 返回男女生各自的總?cè)藬?shù) Query query = em.createQuery(" select p.sex, count(p) from Person p group by p.sex "); // 集合中的元素不再是 Person, 而是一個(gè) Object[] 對(duì)象數(shù)組 List result = query.getResultList(); 如果還需要加上查詢條件,需要使用 "HAVING" 條件語(yǔ)句而不是 "WHERE" 語(yǔ)句 例: // 返回人數(shù)超過(guò) 1 人的性別 Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex having count(*) >?1"); // 設(shè)置查詢中的參數(shù) query.setParameter(1, new Long(1)); // 集合中的元素不再是 Person, 而是一個(gè) Object[] 對(duì)象數(shù)組 List result = query.getResultList(); 關(guān)聯(lián) (join) JPQL 仍然支持和 SQL 中類似的關(guān)聯(lián)語(yǔ)法: left out join/left join inner join left join fetch/inner join fetch left out join/left join 等,都是允許符合條件的右邊表達(dá)式中的 Entiies 為空( 需要顯式使用 left join/left outer join 的情況會(huì)比較少。 例: // 獲取 26 歲人的訂單 , 不管 Order 中是否有 OrderItem select o from Order o left join o.orderItems where o.ower.age=26 order by o.orderid inner join 要求右邊的表達(dá)式必須返回 Entities 例: // 獲取 26 歲人的訂單 ,Order 中必須要有 OrderItem select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid !!重要知識(shí)點(diǎn) 在默認(rèn)的查詢中, Entity 中的集合屬性默認(rèn)不會(huì)被關(guān)聯(lián),集合屬性默認(rèn)是延遲加載 ( lazy-load ) 。那么, left fetch/left out fetch/inner join fetch 提供了一種靈活的查詢加載方式來(lái)提高查詢的性能。 例: private String QueryInnerJoinLazyLoad(){ // 默認(rèn)不關(guān)聯(lián)集合屬性變量 (orderItems) 對(duì)應(yīng)的表 Query query = em.createQuery("select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid"); List result = query.getResultList(); if (result!=null && result.size()>0){ // 這時(shí)獲得 Order 實(shí)體中 orderItems( 集合屬性變量 ) 為空 Order order = (Order) result.get(0); // 當(dāng)需要時(shí), EJB3 Runtime 才會(huì)執(zhí)行一條 SQL 語(yǔ)句來(lái)加載屬于當(dāng)前 Order //OrderItems Set<OrderItem> list = order.getOrderItems (); Iterator<OrderItem> iterator = list.iterator(); if (iterator.hasNext()){ OrderItem orderItem =iterator.next(); System.out.println (" 訂購(gòu)產(chǎn)品名: "+ orderItem.getProductname()); } } 上面代碼在執(zhí)行 "select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid" 時(shí)編譯成的 SQL 如下( 他不包含集合屬性變量 (orderItems) 對(duì)應(yīng)表的字段 select order0_.orderid as orderid6_, order0_.amount as amount6_, order0_.person_id as person4_6_, order0_.createdate as createdate6_ from Orders order0_ inner join OrderItems orderitems1_ on order0_.orderid=orderitems1_.order_id, Person person2_ where order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid 上面代碼當(dāng)執(zhí)行到 Set<OrderItem> list = order.getOrderItems(); 時(shí)才會(huì)執(zhí)行一條 SQL 語(yǔ)句來(lái)加載 屬于當(dāng)前 Order OrderItems ,編譯成的 SQL 如下 select orderitems0_.order_id as order4_1_, orderitems0_.id as id1_, orderitems0_.id as id7_0_, orderitems0_.order_id as order4_7_0_, orderitems0_.productname as productn2_7_0_, orderitems0_.price as price7_0_ from OrderItems orderitems0_ where orderitems0_.order_id=? order by orderitems0_.id ASC 這樣的查詢性能上有不足的地方 。為了查詢 N 個(gè) Order ,我們需要一條 SQL 語(yǔ)句獲得所有的 Order 的原始對(duì)象屬性,但需要另外 N 條語(yǔ)句獲得每個(gè) Order orderItems 集合屬性。為了避免 N+1 的性能問(wèn)題,我們可以利用 join fetch 一次過(guò)用一條 SQL 語(yǔ)句把 Order 的所有信息查詢出來(lái) 例子 // 獲取 26 歲人的訂單 ,Order 中必須要有 OrderItem Query query = em.createQuery("select o from Order o inner join fetch o.orderItems where o.ower.age=26 order by o.orderid"); 上面這句HPQL編譯成以下的 SQL select order0_.orderid as orderid18_0_, orderitems1_.id as id19_1_, order0_.amount as amount18_0_,order0_.person_id as person4_18_0_, order0_.createdate as createdate18_0_, orderitems1_.order_id as order4_19_1_, orderitems1_.productname as productn2_19_1_, orderitems1_.price as price19_1_, orderitems1_.order_id as order4_0__, orderitems1_.id as id0__ from Orders order0_ inner join OrderItems orderitems1_ on order0_.orderid=orderitems1_.order_id, Person person2_ where order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid, orderitems1_.id ASC 上面由于使用了 fetch, 這個(gè)查詢只會(huì)產(chǎn)生一條 SQL 語(yǔ)句,比原來(lái)需要 N+1 SQL 語(yǔ)句在性能上有了極大的提升 排除相同的記錄 DISTINCT 使用關(guān)聯(lián)查詢,我們很經(jīng)常得到重復(fù)的對(duì)象,如下面語(yǔ)句: " select o from Order o inner join fetch o.orderItems order by o.orderid " 當(dāng)有 N 個(gè) orderItem 時(shí)就會(huì)產(chǎn)生 N 個(gè) Order, 而有些 Order 對(duì)象往往是相同的,這時(shí)我們需要使用 DISTINCT 關(guān)鍵字來(lái)排除掉相同的對(duì)象 例: select DISTINCT o from Order o inner join fetch o.orderItems order by o.orderid 比較 Entity 在查詢中使用參數(shù)查詢時(shí) ,參數(shù)類型除了 String, 原始數(shù)據(jù)類型 ( int, double ) 和它們的對(duì)象類型 ( Integer, Double ), 可以是 Entity 的實(shí)例 例: // 查詢某人的所有訂單 Query query = em.createQuery("select o from Order o where o.ower =?1 order by o.orderid"); Person person = new Person(); person.setPersonid(new Integer(1)); // 設(shè)置查詢中的參數(shù) query.setParameter(1,person); 批量更新 (Batch Update) HPQL支持批量更新 例: // 把所有訂單的金額加 10 Query query = em.createQuery(" update Order as o set o.amount=o.amount+10 "); //update 的記錄數(shù) int result = query. executeUpdate (); 批量刪除 (Batch Remove) 例: // 把金額小于100的訂單刪除,先刪除訂單子項(xiàng),再刪除訂單 Query query = em .createQuery( "delete from OrderItem item where item.order in(from Order as o where o.amount<100)" ); query. executeUpdate(); query = em .createQuery( "delete from Order as o where o.amount<100" ); query.executeUpdate(); //delete 的記錄數(shù) 使用操作符 NOT // 查詢除了指定人之外的所有訂單 Query query = em.createQuery("select o from Order o where not(o.ower =?1) order by o.orderid"); Person person = new Person(); person.setPersonid(new Integer(2)); // 設(shè)置查詢中的參數(shù) query.setParameter(1,person); 使用操作符 BETWEEN select o from Order as o where o.amount between 300 and 1000 使用操作符 IN // 查找年齡為 26,21 Person select p from Person as p where p.age in(26,21) 使用操作符 LIKE // 查找以字符串 "li" 開頭的 Person select p from Person as p where p.name like 'li%' 使用操作符 IS NULL // 查詢含有購(gòu)買者的所有 Order select o from Order as o where o.ower is [not] null 使用操作符 IS EMPTY IS EMPTY 是針對(duì)集合屬性 (Collection) 的操作符 。可以和 NOT 一起使用 注:低版權(quán)的 Mysql 不支持 IS EMPTY // 查詢含有訂單項(xiàng)的所有 Order select o from Order as o where o.orderItems is [not] empty 使用操作符 EXISTS [NOT]EXISTS 需要和子查詢配合使用 。注:低版權(quán)的 Mysql 不支持 EXISTS // 如果存在訂單號(hào)為 1 的訂單,就獲取所有 OrderItem select oi from OrderItem as oi where exists (select o from Order o where o.orderid=1) // 如果不存在訂單號(hào)為 10 的訂單,就獲取 id 1 OrderItem select oi from OrderItem as oi where oi.id=1 and not exists (select o from Order o where o.orderid=10) 字符串函數(shù) JPQL 定義了內(nèi)置函數(shù)方便使用。這些函數(shù)的使用方法和 SQL 中相應(yīng)的函數(shù)方法類似。包括: 1. CONCAT 字符串拼接 2. SUBSTRING 字符串截取 3. TRIM 去掉空格 4. LOWER 轉(zhuǎn)換成小寫 5. UPPER 裝換成大寫 6. LENGTH 字符串長(zhǎng)度 7. LOCATE 字符串定位 例: // 查詢所有人員,并在姓名后面加上字符串 "_foshan" select p.personid, concat(p.name, '_foshan') from Person as p // 查詢所有人員 , 只取姓名的前三個(gè)字符 select p.personid, substring (p.name,1,3) from Person as p 計(jì)算函數(shù) HPQL 定義的計(jì)算函數(shù)包括: ABS 絕對(duì)值 SQRT 平方根 MOD 取余數(shù) SIZE 取集合的數(shù)量 例: // 查詢所有 Order 的訂單號(hào)及其訂單項(xiàng)的數(shù)量 select o.orderid, size (o.orderItems) from Order as o group by o.orderid // 查詢所有 Order 的訂單號(hào)及其總金額 /10 的余數(shù) select o.orderid, mod (o.amount, 10) from Order as o 子查詢 子查詢可以用于 WHERE HAVING 條件語(yǔ)句中 例: // 查詢年齡為 26 歲的購(gòu)買者的所有 Order select o from Order as o where o.ower in(select p from Person as p where p.age =26) 結(jié)果集分頁(yè) 有些時(shí)候當(dāng)執(zhí)行一個(gè)查詢會(huì)返回成千上萬(wàn)條記錄,事實(shí)上我們只需要顯示一部分?jǐn)?shù)據(jù)。這時(shí)我們需要對(duì)結(jié)果集進(jìn)行分頁(yè) QueryAPI 有兩個(gè)接口方法可以解決這個(gè)問(wèn)題: setMaxResults( ) setFirstResult( ) setMaxResults 方法設(shè)置獲取多少條記錄 setFirstResult 方法設(shè)置從結(jié)果集中的那個(gè)索引開始獲取 (假如返回的記錄有 3 條,容器會(huì)自動(dòng)為記錄編上索引,索引從 0 開始,依次為 0 1 2 例: public List getPersonList( int max, int whichpage) { try { int index = (whichpage-1) * max; Query query = em .createQuery( "from Person p order by personid asc" ); List list = query. setMaxResults(max) . setFirstResult(index) . getResultList(); em .clear(); // 分離內(nèi)存中受EntityManager管理的實(shí)體bean,讓VM進(jìn)行垃圾回收 return list; } catch (Exception e) { e.printStackTrace(); return null ; } }

總結(jié)

以上是生活随笔為你收集整理的EJB3.0 JPQL的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。