简单查询
返回所有Topic对象的记录:
SELECT t FROM Topic t
按条件查询Topic:
SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = ?1
?1表示用位置标识参数,通过Query的setParameter(1, "主题1")绑定参数。DISTINCT表示过滤重复数据。
如果以命名绑定数据,改成:
SELECT DISTINCT t FROM Topic t WHERE t.topicTitle = :title
需要通过Query的setParameter("title", "主题1")绑定参数。
关联查询
1.One To Many
返回PollOptions对应的PollTopic对象,可以:
SELECT DISTINCT p FROM PollTopic p, IN(p.options) o WHERE o.optionItem LIKE ?1
语法和SQL以及HQL都有很大的区别,它直接实体属性连接关联的实体,通过PollTopic的options属性关联到PollOption实体上。
该查询语句的另外两种等价写法分别是:
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 |
2.Many To One
希望查询某一个调查主题下的所示调查项,可以:
SELECT p FROM PollOption p JOIN p.pollTopic t WHERE t.topicId = :topicId |
关系操作符
空值比较符:is null、is not null 、is empty、is not empty
范围比较符:BETWEEN..AND和>、>= 、<、<=、<>。
子查询
支持EXISTS、ALL、ANY。如查询出拥有6个以上选项的调查主题:
SELECT t FROM PollTopic t WHERE (SELECT COUNT(o) FROM t.options o) > 6 |
可用函数
◆ 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或JPA查询语言进行实体的更新、删除操作。
1.更新:
UPDATE PollOption p SET p.optionItem = :value WHERE p.optionId = :optionId
2.删除:
DELETE FROM PollOption p WHERE p.optionId = :optioned
之后使用Query接口的executeUpdate()方法执行更新、删除。
排序和分组
排序:Order by 属性名 desc [asc]
聚集函数:
◆AVG:平均值,返回double;
◆MAX:最大值;
◆MIN:最小值;
◆SUM:累加和;
◆COUNT:集合数
通过HAVING对聚集结果进行条件过滤:
SELECT COUNT(p),p.pollTopic.topicId FROM PollOption p GROUP BY p.pollTopic.topicId HAVING p.pollTopic.topicId IN(1,2,3) |
如何取得结果?注意使用聚集函数不是返回一个对应的实体List,而是返回一个List<Object>,以下是返回上面查询的结果(使用Object数组):
List list= query.list();
Object obj[] = null;//声明对象数组
Integer count = null;
Integer topicId = null;
for(int i=0;i<list.size();i++){
obj = (Object[]) list.get(i);
count = (Integer) obj[0];
topicId = (Integer) obj[1];
//逻辑操作
}
select name ,age from user; //原生SQL语句
select u.name,u.age from User u; //JPQL语句
select u from User u; //JPQL语句
SQL语句是在数据库空间中对字段,列,行进行操作
JPQL语句是在EJB实体空间中面向对象,属性进行操作
JPQL必须由JPA的JPQL解析器解析为SQL才能执行,必须先获取Query对象
参数查询
1命名参数查询
entityManager.createQuery("select u from User u where u.age=:param");
query.setParameter("param",24);
List<User> result=(List<User>)query.getResultList();
2位置参数查询
"select u from User u where u.age=?1"
query.setParameter(1,24);
3实体参数(JPQL中除了基本类型外,还可以是对象类型)
"select u from User u where u.person=?1"
Person p=new Person();
p.setId(1);
query.setParameter(1,p);
JPQL运算符
算术运算符 + - * /
关系运算符 = > < >= <= <>
逻辑运算符 between ,like , in , is null,is empty,member of,not ,and ,or
1 not
"select u from User u where not(u.cityid=?1)"
2 between和sql中一样
3 in 在给定的值列表中查询
"select u from User u where u.cityid in(1,2,3)"
4 like ( _ 表示一个字符,%表示任意数量字符 )
xxxx where u.name like ' 张% '
5 is null (实体的属性是否为空,即实体属性映射的字段是否为空)
"select u from User u where u.cityid is null"
6 is empty (与is null 不同的是,它针对实体的集合属性 内有没有元素。
虽然集合对象是存在的,但是集合内没有元素)
select o from Order o where o.orderItems is empty
条件查询
1排序查询 asc升序 desc降序
order by p.age desc,p.birthday asc
2聚合函数查询
avg() 平均值,返回Double count()返回Long max() min() sum()
以上除了count外其它的函数的参数对应的是 单个的字段,即属性而不是对象
HAVING和WHERE的区别。一个是先分组,再对组进行筛选;一个是先筛选,然后对筛选后的记录进行分组。
构造器查询
"select new com.jsun.Person(p.name) from Person p"
Person有这个构造器时,即Person(String name),成功返回对象。
关联查询(实际工作中仍然会有这种需求)
left join 允许右边实体表达式的实体为空,这里的实体指 集合属性
inner join 右边必须存在
"select o from Order o inner join o.orderItems"
在默认查询中,集合属性是懒加载的。只有用的时候JPA才会再发SQL语句
在查询的时候我们希望一次全抓取出来怎么办?用 fetch
(其实left join和inner join在这里使用主要是为了配合fetch,一次抓取,因为默认的是懒加载)
"select o from Order oinner join fetcho.orderItems"
排除相同记录DISTINCT
select distinct o from Order o
(还可以配合聚合函数使用)
如 select count(distinct o) from Order o
JPQL内置函数
字符串函数
concat(str1,str2)
substring(string,position,length)
trim( [leading | trailing | both] sub_str from str)
upper(str)
lower(str)
length(str)
locate(searchString,initPosition)
日期,时间函数
CURRENT_DATE //返回当前日期(这是数据库端的时间)
CURRENT_TIME //返回当前时间
CURRENT_TIMESTAMP //返回当前日期时间
数学函数
ABS(number) //绝对值
SQRT(number) //平方根
MOD(num,div)//取模
SIZE(collection) //返回集合中元素的数量
如:select o from Order o where size(o.items)>10
使用子查询
xxxx in(子查询)
xxxx not in(子查询)
exists(子查询)
notexists(子查询 ) exists存在的意思 即子查询的结果不为空就是存在
分页查询
用到了query接口的两个方法
setMaxResults(int) //设置获取多少条记录
和setFirstResult(int)//结果集开始的索引,索引默认从0开始
以上两个方法都返回Query对象所以可以组成方法链
query.setMaxResults(max).setFirstResult(index).getResultList()
批量操作(批量更新和批量删除)
建议将所有批量操作与不连续的事务隔离开,
批量操作可能造成受管实体与数据库的不一致
原生SQL查询与调用存储过程(EJB3.0不支持以OUT参数的形式返回的存储过程)
Query query=entityManager.createNativeQuery(" {call pro_1(?)} ");
query.setParameter(1,"jsun");
//无返回值存储过程
query.executeUpdate();
//返回单个值的存储过程
String result=(String)query.getSingleResult();
//返回全部列的存储过程
List<User> results=(List<User>)query.getResultList();
//返回部分列的存储过程
List<Object[]> results=(List<Object[]>)query.getResultList();
for(Object[] row:results){
row[0],row[1]
}