技术开发 频道

JPA重整ORM山河


IT168分析评论】 
    6.JPA的查询语言
    JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。 
    简单的查询 
    你可以使用以下语句返回所有Topic对象的记录: 
    SELECT t FROM Topic t 
    t表示Topic的别名,在Topic t是Topic AS t的缩写。 
    如果需要按条件查询Topic,我们可以使用: 
    SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = ?1 
    通过WHERE指定查询条件,?1表示用位置标识参数,尔后,我们可以通过Query的setParameter(1, "主题1")绑定参数。而DISTINCT表示过滤掉重复的数据。 
    如果需要以命名绑定绑定数据,可以改成以下的方式: 
    SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = :title 
    这时,需要通过Query的setParameter("title", "主题1")绑定参数。 

    关联查询:从One的一方关联到Many的一方 
    返回PollOptions对应的PollTopic对象,可以使用以下语句: 
    SELECT DISTINCT p FROM PollTopic p, IN(p.options) o WHERE o.optionItem LIKE ?1 
    这个语法和SQL以及HQL都有很大的区别,它直接实体属性连接关联的实体,这里我们通过PollTopic的options属性关联到PollOption实体上,对应的SQL语句为: 
    SELECT DISTINCT t0.TOPIC_ID, t0.TOPIC_TYPE, t0.TOPIC_TITLE, t0.TOPIC_TIME, t0.TOPIC_VIEWS, t0.MULTIPLE, t0.MAX_CHOICES FROM T_TOPIC t0, T_POLL_OPTION t1 WHERE (((t1.OPTION_ITEM LIKE ?) AND (t0.TOPIC_TYPE = ?)) AND (t1.TOPIC_ID = t0.TOPIC_ID)) 
    该查询语句的另外两种等价的写法分别是: 
    SELECT DISTINCT p FROM PollTopic p JOIN p.options o WHERE o.optionItem LIKE ?1

SELECT DISTINCT p FROM PollTopic p WHERE p.options.optionItem LIKE ?1 

    关联查询:从Many的一方关联到One的一方 
    从Many一方关联到One一方的查询语句和前面所讲的也很相似。如我们希望查询某一个调查主题下的所示调查项,则可以编写以下的查询语句: 
    SELECT p FROM PollOption p JOIN p.pollTopic t WHERE t.topicId = :topicId 
    对应的SQL语句为: 
    SELECT t0.OPTION_ID, t0.OPTION_ITEM, t0.TOPIC_ID FROM T_POLL_OPTION t0, T_TOPIC t1 WHERE ((t1.TOPIC_ID = ?) AND ((t1.TOPIC_ID = t0.TOPIC_ID) AND (t1.TOPIC_TYPE = ?))) 

    使用其它的关系操作符 
    使用空值比较符,比如查询附件不空的所有帖子对象: 
    SELECT p FROM Post p WHERE p.postAttach IS NOT NULL 
    范围比较符包括BETWEEN..AND和>、>= 、<、<=、<>这些操作符。比如下面的语句查询浏览次数在100到200之间的所有论坛主题: 
    SELECT t FROM Topic t WHERE t.topicViews BETWEEN 100 AND 200 

    集合关系操作符 
    和其它实体是One-to-Many或Many-to-Many关系的实体,通过集合引用关联的实体,我们可以通过集合关系操作符进行数据查询。下面的语句返回所有没有选项的调查论坛的主题: 
    SELECT t FROM PollTopic t WHERE t.options IS EMPTY 
    我们还可以通过判断元素是否在集合中进行查询: 
    SELECT t FROM PollTopic t WHERE :option MEMBER OF t.options 
    这里参数必须绑定一个PollOption的对象,JPA会自动将其转换为主键比较的SQL语句。 

    子查询 
    JPA可以进行子查询,并支持几个常见的子查询函数:EXISTS、ALL、ANY。如下面的语句查询出拥有6个以上选项的调查主题: 
    SELECT t FROM PollTopic t WHERE (SELECT COUNT(o) FROM t.options o) > 6 
    
    可用函数 
    JPA查询支持一些常见的函数,其中可用的字符串操作函数有:
 CONCAT(String, String):合并字段串;
 LENGTH(String):求字段串的长度;
 LOCATE(String, String [, start]):查询字段串的函数,第一个参数为需要查询的字段串,看它在出现在第二个参数字符串的哪个位置,start表示从哪个位置开始查找,返回查找到的位置,没有找到返回0。如LOCATE ('b1','a1b1c1',1)返回为3;
 SUBSTRING(String, start, length):子字段串函数;
 TRIM([[LEADING|TRAILING|BOTH] char) FROM] (String):将字段串前后的特殊字符去除,可以通过选择决定具体的去除位置和字符;
 LOWER(String):将字符串转为小写;
 UPPER(String):将字符串转为大写。
数字操作函数有:
 ABS(number):求绝对值函数;
 MOD(int, int):求模的函数;
 SQRT(double):求平方函数;
 SIZE(Collection):求集合大小函数。 

    更改语句 
    可以用EntityManager进行实体的更新操作,也可以通过查询语言执行数据表的字段更新,记录删除的操作: 
    下面的语句将某一个调查选项更新为新的值: 
    UPDATE PollOption p SET p.optionItem = :value WHERE p.optionId = :optionId 
    我们使用Query接口的executeUpdate()方法执行更新。下面的语句删除一条记录: 
    DELETE FROM PollOption p WHERE p.optionId = :optionId 

    排序和分组 
    我们还可以对查询进行排序和分组。如下面的语句查询出主题的发表时间大于某个时间值,返回的结果按浏览量降序排列:
SELECT t FROM Topic t WHERE t.topicTime > :time ORDER BY t.topicViews DESC 
    下面的语句计算出每个调查主题对应的选项数目: 
    SELECT COUNT(p),p.pollTopic.topicId FROM PollOption p GROUP BY p.pollTopic.topicId
这里,我们使用了计算数量的聚集函数COUNT(),其它几个可用的聚集函数分别为:
 AVG:计算平均值,返回类型为double;
 MAX:计算最大值;
 MIN:计算最小值;
 SUM:计算累加和;
我们还可以通过HAVING对聚集结果进行条件过滤:
SELECT COUNT(p),p.pollTopic.topicId FROM PollOption p GROUP BY p.pollTopic.topicId HAVING p.pollTopic.topicId IN(1,2,3) 

    7.小结 
    在不久的将来,Sun可能会将JPA作为一个单独的JSR对待,同时JPA还可能作为Java SE的一部分。不过这些都不太重要,重要的是,我们现在已经可以在脱离容器的情况下、在Java SE应用中使用JPA了。 
    JPA已经作为一项对象持久化的标准,不但可以获得Java EE应用服务器的支持,来可以直接在Java SE中使用。开发者将无需在现有多种ORM框架中艰难地选择,按照Sun的预想,现有ORM框架头顶的光环将渐渐暗淡,不再具有以往的吸引力。
0
相关文章