SQL语句是在数据库空间中对字段,列,行进行操作
JPQL语句是在EJB实体空间中面向对象,属性进行操作
JPQL必须由JPA的JPQL解析器解析为SQL才能执行,必须先获取Query对象
参数查询
1、命名参数查询
Query query = em.createQuery("select u from User u where u.age=:param");
query.setParameter("param",24);
List<User> result=(List<User>)query.getResultList();
2、位置参数查询
Query query = em.createQuery("select u from User u where u.age=?1");
query.setParameter(1,24);
3、实体参数
JPQL中除了基本类型外,还可以是对象类型
Query query = em.createQuery(""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)
或者
String jpql="FROM Employee where empName IN (:ids)";
Query query= em.createQuery(jpql);
List<String> params = new ArrayList<String>();
params.add("张三");
params.add("李四");
query.setParameter("ids", params);
List list = query.getResultList();
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外其它的函数的参数对应的是 单个的字段,即属性而不是对象
3、HAVING和WHERE的区别
HAVING是先分组,再对组进行筛选;
WHERE是先筛选,然后对筛选后的记录进行分组。
关联查询
实际工作中仍然会有这种需求
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 o inner join fetch o.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(子查询)
not exists(子查询 ) exists存在的意思 即子查询的结果不为空就是存在
分页查询
用到了query接口的两个方法
setMaxResults(int) //设置获取多少条记录
和setFirstResult(int)//结果集开始的索引,索引默认从0开始
以上两个方法都返回Query对象所以可以组成方法链
query.setMaxResults(max).setFirstResult(index).getResultList()
批量操作(批量更新和批量删除)
建议将所有批量操作与不连续的事务隔离开,
批量操作可能造成受管实体与数据库的不一致
有的时候我们需要循环保存数据,当保存大量数据的时候,
如果到最后才提交所有数据,那么数据库的负载可能会比较大。我们可以这样做,每30个记录就提交(flush)一次。
代码如下(每到30条记录的时候就强制提交):
public void updateBatch(List list) {
for (int i = 0; i < list.size(); i++) {
em.merge(list.get(i)); //变成托管状态
if (i % 30 == 0) {
em.flush(); //变成持久化状态
em.clear(); //变成游离状态
}
}
}
public void saveBatch(List list) {
for (int i = 0; i < list.size(); i++) {
em.persist(list.get(i)); //变成托管状态
if (i % 30 == 0) {
em.flush(); //变成持久化状态
em.clear(); //变成游离状态
}
}
}
调用存储过程
原生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]
}