Spring Data Jpa系列教程(三)--------JPQL

    高尔基曾经说过——"要想用好Spring Data Jpa,必须学会JPQL"。   

    嘿嘿嘿。学过Hibernate的同学可能知道,hibernate中有一个hql,它跟数据库无关,可以自动翻译成对应数据库的sql,

JPQL也是如此,它是一个可移植的面向对象的语言。直接开始吧,我等不及了!

 

要从 Java 代码内发出 JPQL 查询,您需要利用 EntityManager API 和 Query API 的相应方法,执行以下一般步骤:

1.   使用注入或通过 EntityManagerFactory 实例获取一个 EntityManager 实例。

2.   通过调用相应 EntityManager 的方法(如 createQuery),创建一个 Query 实例。

3.   如果有查询参数,使用相应 Query 的 setParameter 方法进行设置。

4.   如果需要,使用 setMaxResults 和/或 setFirstResult Query 的方法设置要检索的实例的最大数量和/或指定检索的起始实例位置。

5.   如果需要,使用 setHint Query 的方法设置供应商特定的提示。

6.   如果需要,使用 setFlushMode Query 的方法设置查询执行的刷新模式,覆盖实体管理器的刷新模式。

7.   使用相应 Query 的方法 getSingleResult 或 getResultList 执行查询。如果进行更新或删除操作,您必须使用 executeUpdate 方法,它返回已更新或删除的实体实例的数量。

    @PersistenceContext
    private EntityManager em;  // 注入实体管理器
    @SuppressWarnings("unchecked")
    public Page<Student> search(User user) {
        String dataSql = "select t from User t where 1 = 1";
        String countSql = "select count(t) from User t where 1 = 1";
        
        if(null != user && !StringUtils.isEmpty(user.getName())) {
            dataSql += " and t.name = ?1";
            countSql += " and t.name = ?1";
        }
        
        Query dataQuery = em.createQuery(dataSql);
        Query countQuery = em.createQuery(countSql);
        
        if(null != user && !StringUtils.isEmpty(user.getName())) {
            dataQuery.setParameter(1, user.getName());
            countQuery.setParameter(1, user.getName());
        }long totalSize = (long) countQuery.getSingleResult();
        Page<User> page = new Page();
        page.setTotalSize(totalSize);
        List<User> data = dataQuery.getResultList();
        page.setData(data);
        return page;
    }

JPQL详细介绍

                          User   -------------->interests  多对多关系,

JPQL :  

select u  from User u

select u.name u.income from User u  

貌似和sql没啥区别对吧, 好到这里先做个简单实例,我们现说下概念:

算术运算符:

+   -   *   /

select u from User u where (u.income + 2000) = 5000

关系运算符:

 =      >     <     >=     <=

逻辑运算符:

between,like,in,is null,is empty,member of ,not,and ,or

is null 用来判断普通属性,

is empty用来判断集合属性,

member of的话,emmm.。。。。举个栗子:

查出所有喜欢体育的User:select u from User u where :interest member of u.interests

(冒号加一个名字是JPQL的一种传参方式见下面的JPQL动态查询)这里的:interests是传入的体育这个兴趣实体对象,没错就是Java对象!

JPQL函数

字符串函数

concat,substring,trim,upper,lower,length,locate

concat拼接字符串,

trim(leading,'小', from u.name)表示去掉左边的'小'字符串

       trailing表示右边,both表示两边, 而去掉空格能直接trim(u.name)

locate是定位函数,locate('小',u.name,1)表示'小'出现的位置,开始找的位置最小从1开始。

时间函数

CURRENT_DATE  日期,CURRENT_TIME 时间, CURRENT_TIMESTAMP日期时间

算术函数

ABS绝对值

SQRT平方根

MOD取模

SIZE集合数量(只用在where 中)

例如:select u.name from User u where size(u.interests)=2  查出有2个兴趣的人。

JPQL分页

和Hibernate差不多,用Query的setFirstResult和setMaxResult设置开始位置和个数

JPQL分组查询:

group by ..... having

聚合函数:avg(distinct),sum(distinct),count(distinct),min(distinct),max(distinct)

JPQL连接查询:

左连接:

selecy a.id,a.name,b.id,b.name from A a left join a.b b   

关联查询:

select u from User u (left) join fetch u.interests i

JPQL动态查询:

基于位置参数 :   用?接数字表示参数位置,如?1,?2,设置参数就query.setparameter(1,name);

基于名称绑定: 用:id  冒号加上一个参数名字,query.setparameter("id",name);

 

查询中使用构造器(Constructor)

可以在SELECT子句中使用构造器返回一个或多个java实例。如下所示:

Query query = em.createQuery("select new com.demo.bean.Person(p.id, p.name) from Person p order by p.id desc");

JPQL本地化查询,即直接使用sql查询,移植到其他数据库需要修改代码,并且需要手动做结果映射

Query query = entityManager.createNativeQuery("");

命名查询

可以在实体bean上通过@NamedQuery or @NamedQueries预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把使用频率高的查询语句定义成命名查询。

定义单个命名查询:

@NamedQuery(name="getPerson", query= "select p from  Person p where p.id=?1")

@Entity
public class Person implements Serializable{

如果要定义多个命名查询,应在@javax.persistence.NamedQueries里定义@NamedQuery

@NamedQueries({

@NamedQuery(name="getPerson", query= "select p from  Person p where p.id=?1"),

@NamedQuery(name="getPersonList", query= "select p from Person as p where p.age>?1")

})

@Entity

public class Person implements Serializable{

当命名查询定义好了之后,我们就可以通过名称执行其查询。代码如下:

Query query = em.createNamedQuery("getPerson");

query.setParameter(1, 1);

就到这里吧,下一张讲高级查询,博客写的不好,有什么问题直接家QQ问我,或者留言都行。。

 

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值