Query API 通过javax.persistence.Query接口来实现查询功能,而Query接口可以通过javax.persistence. EntityManager得到。 参数 EJB QL支持具名参数(named parameters)和指示参数(positional parameters),如: Query query=entityManager.createQuery(“from Customer c where c.firstName=:first and c.lastName=:last”); query.setParameter(“first”,first); query.setParameter(“last”,last); return query.getResultList(); 或者 Query query=entityManager.createQuery(“from Customer c where c.firstName=?1 and c.lastName=?2”); query.setParameter(1,first); query.setParameter(2,last); return query.getResultList();
EJB QL EJB QL是按照实体的抽象持久结构来表达的,包括:抽象结构名称、基本成员属性和关系型成员属性。抽象结构名,默认是非限定类名,如果使用了 @Entity(name=”Cust”) public class Customer{….} 那么查询Customer 的EJB QL为 select c from Cust AS c;
简单查询 select object(c) from Customer as c 等价于select c from Customer as c
选择实体和关系型成员属性 对于 @Entity public class Customer{ private int id; private String first; private Address address; @Id public int getId(){…..} public getFirstName(){return first;} ………… } 选择成员属性可以使用: select c.firstName from Customer as c;或者 select c.first from Customer as c; 选择关联的实体可以使用: select c.address from Customer as c; 选择关联实体的属性可以使用: select c.address.city from Customer as c; 但是如果Address不是持久型成员,只是普通的class,上面的语句是非法的。可以使用 @Embedded private Address address;让语句变回合法。
构造函数表达式 可以在select子句是指定一个构造函数,用于创建普通的JAVA对象(而非实体),如: select new com.tian.domain.Name(c.firstName,c.lastName) from Customer c;
IN操作符和INNER JOIN 返回所有乘客的所有预订信息 select r from Customer as c ,in(c.reservations) r; 等效于 select r from Customer as c inner join c.reservations r;//inner可以省略
LEFT JOIN 查询所有顾客及他们的电话号码,如果顾客没有电话号码以null代替 select c.firstName ,p.number from Customer c left join c.phoneNumbers p; //left join可以写成left outer join
Fetch Joins 如果关系型成员属性FetchType在定义XML时(或注解)设为LAZY,那么在程序访问到这些成员时才从数据库加载数据,有时会增加数据库访问量,可以通过JOIN FETCH强制加载这些关系成员,如: select c from customer c left join fetch c.phones;这时会提前加载Phone关联
使用DISTINCT 关键字distinct确保查询不会返回重复项。如查询所有预订舱位的顾客,由于顾客可以预订多次,所有distinct可以派上用场。 select distinct cust from Reservation as res, in (res.customers) cust;
where 子句与字面常量 where 子句用于缩小选择范围。如果使用到字符串常量,可以使用单引号括起来,如果字符串中又有一个单引号,请用两个单引号表示 ;如果是数值型的常量,就直接书写;如果是布尔型,常量取值用true和false。如 where name=’capital one’; where name=’wendy’’s’;where hasGoodCredit=true; 如果不想涉及这些细节,可以直接使用查询参数,让查询API处理这些问题
where 子句与运算符的优先级 点号(.)à数学运算符(+-*/)à比较运算符(=,>,like,between,in,is null,is empty,member of)à逻辑运算符(not,and or)
where子句与数学运算符 允许查询操作在做比较时执行算术运算。运算过程中,数值也许被放宽或提升,如int 与double相乘,先把int 变成double,结果也是double的 where子句和逻辑运算符 and 和or运算符的行为与java语言中的&&和||有所不同。&&只有左操作数为true时才会对右操作数求值,and要由转换出的原生语言决定 where 子句和in IN用来检验是否与一组字面常量中的元素相匹配,如: where c.address.state IN(‘FL’,’TX’,’WI’); 也可以使用参数 where c.address.state IN(?1,?2,?3,5.7); where 子句与is null 比较运算符is null允许检验路径表达式是否为null。它也可以用来检验输入参数,如 select c from Customer as c where :city is not null and :state is not null and c.address.state=:state where 子句与is empty is empty检验集合类型的关系是否为空(没有元素),集体类型的关系是从不会为null的。对from子句已经被赋予标识符的集合型关系使用is empty是非法的,如: select r from Reservation as r inner join r.customers as c //已经赋予标识符c,表明c一定不为空 where r.customers is not empty; where 子句与member of member of用于判断某个实体是否是集合型关系的一个成员,如 where cust not member of res.customers where子句与like 可以使用两个特殊的字符“%”(表示任意字符序列)和“_”(表示单个字符),如果字符串本来就有%或_,可以使用“\”字符来避免冲突
ORDER BY子句 对返回集合进行排序。在EJB QL中有一个使用限制:order by子句中出现的属性,必须出现在select子句中,或者是select子句选中实体的一个属性。如: select c from Customers as c order by c.address desc;select addr.zip from Address as addr order by add.zip; 以下是非法的 select c from Customers as c order by c.address.city desc;// city不是c的直接属性 GROUP BY 与HAVING group by 用于分组,having对分组进一步筛选。group by子句中指定的字段必须出现于查询的返回结果中,这和SQL的要求是一致的。
子查询 子查询是内嵌于主查询的另一个查询。EJB QL支持在where和having子句中使用子查询 查询费用超过$100,000的所有航程 from Cruise cr where 100000<(select sum(res.amountPaid) from cr.reservations res) ALL,ANY,SOME 如果子查询返回多项结果,可以使用ALL、ANY和SOME对结果做进一步限定 如果子查询中的所有内容都与条件表达式相匹配,那么操作符ALL就返回true 查询所有预付了舱位预订定金的航程 from Cruise cr where 0< all(select res.amountPaid from cr.reservations res) 如果子查询中的有任意一项与条件表达式相匹配,那么操作符ALL或SOME就返回true EXISTS 如果子查询包含一项或多项结果,那么操作符EXISTS返回true
批量的UPDATE与DELETE 给所有名叫Bill Burke的乘客增加$10 update Reservation res set res.amountPaid=(res.amountPaid+10) where exists( select c from res.customers c where c.firstName=’Bill’ and c.lastName=’Burke’ ); 是否可以写成? update Reservation res set res.amountPaid=(res.amountPaid+10) where res.customers.firstName=’Bill’ and res.customers.lastName=’Burke’
删除所有Bill Burke的舱位预订记录 delect from Reservation res where exist( select c from res.customers c where c.firstName=’Bill’ and c.lastName=’Burke’ )