Spring Data JPA入门-JPQL和命名查询

JPQL和命名查询

在使用Spring Data JPA的过程中,框架通过解析方法名称的方式生成对应的SQL,确实为我们减少了很多的工作量,但是,也特殊情况,需要我们手写SQL,当然,这里是JPQL(一种面向对象的SQL语法结构)

使用@Query注解创建查询,将该注解贴在dao的方法上,然后提供一个需要的JPQL语句即可,如:

@Query("SELECT p FROM Person p WHERE name LIKE %?1%")
Person findByName(String name);

如果不使用Query注解,那么Spring Data JPA为我们生成的SQL应该是:

Hibernate: select person0_.id as id1_0_, person0_.age as age2_0_, person0_.name as name3_0_ 
            from Person person0_ where person0_.name=?

使用注解之后执行的SQL:

Hibernate: select person0_.id as id1_0_, person0_.age as age2_0_, person0_.name as name3_0_ 
            from Person person0_ where person0_.name like ?

所以,我们可以通过这种方式来自定义需要执行的SQL语句,这样可以让我们开发者更加自如的来完成我们的需求

很多开发者在创建 JPQL 时喜欢使用命名参数来代替位置编号,@Query 也对此提供了支持。JPQL 语句中通过”: 变量”的格式来指定参数,同时在方法的参数前面使用 @Param 将方法参数与 JPQL中的命名参数对应,示例如下:

@Query("SELECT p FROM Person p WHERE name LIKE %:name%")
Person findByName(@Param("name") String name);

此时大家应该会想一个问题,上面我们都在说如何执行查询操作,查询的SQL可以自动生成也可自定义,那么增删改操作的SQL可以吗?也可以自定生成响应的SQL吗?

答案是肯定的,这里,我们需要使用@Modifying注解来标识该方法执行的是更新或者删除操作,如:

@Modifying
@Query("UPDATE Person p SET p.name = :name WHERE p.id = :id")
void updatePersonName(@Param("id") Integer id, @Param("name") String name);

如此这般,框架执行的就不是查询的SQL,而是更新的SQL

通过调用 JPA 命名查询语句创建查询

命名查询是 JPA 提供的一种将查询语句从方法体中独立出来,以供多个方法共用的功能。Spring Data JPA 对命名查询也提供了很好的支持。用户只需要按照 JPA 规范在 orm.xml 文件或者在实体类中使用 @NamedQuery(或 @NamedNativeQuery)定义好查询语句,唯一要做的就是为该语句命名时,需要满足”DomainClass.methodName”的命名规则。假设定义了如下接口:

Person findByName(@Param("name") String name);

同时在实体类中定义JPQL或者SQL

@NamedQuery(name = "Person.findByName", query = "SELECT p FROM Person p WHERE p.name LIKE :name")
public class Person {
}

此时name属性的值需要按照规则定义,Spring Data JPA根据name属性的值找到对应的JPQL语句并执行

Spring Data JPA的查询策略

以上,我们说到了三种执行SQL的方式,

  1. 框架通过解析方法名称,生成对应的SQL语句
  2. 使用@Query声明JPQL,这样就可以执行我们自定义的语句
  3. Spring Data JPA所支持的命名查询

这里我们来看看框架是如何选择使用哪一种的执行查询的方式:

Spring Data JPA 在为接口创建代理对象时,如果发现同时存在多种上述情况可用,它该优先采用哪种策略呢?为此,<jpa:repositories> 提供了 query-lookup-strategy 属性,用以指定查找的顺序。它有如下三个取值:

  1. create —- 通过解析方法名字来创建查询。即使有符合的命名查询,或者方法通过 @Query 指定的查询语句,都将会被忽略。

  2. create-if-not-found —- 如果方法通过 @Query 指定了查询语句,则使用该语句实现查询;如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该命名查询;如果两者都没有找到,则通过解析方法名字来创建查询。这是 query-lookup-strategy 属性的默认值。

  3. use-declared-query —- 如果方法通过 @Query 指定了查询语句,则使用该语句实现查询;如果没有,则查找是否定义了符合条件的命名查询,如果找到,则使用该命名查询;如果两者都没有找到,则抛出异常。

为接口中的部分方法提供自定义实现
在实际开发中,我们会遇到一些需要自定义持久层实现的需求,也就是Spring Data JPA的实现不能满足我们的要求,所以Spring Data JPA考虑到了这一点,为我们提供了自定义实现持久层的方式

将需要开发者手动实现的方法从持久层接口(假设为 UserDao )中抽取出来,独立成一个新的接口(假设为 IUserDaoBase ),并让 IUserDao 继承 IUserDaoBase;
为 IUserDaoBase 提供自定义实现(假设为 IUserDaoBaseImpl );
将 IUserDaoBaseImpl 配置为 Spring Bean;
在 <jpa:repositories> 中按下面的方式进行配置。

<jpa:repositories base-package="cn.wolfcode.spring_jdbc_jpa.dao"> 
<jpa:repository id="userDao" repository-impl-ref=" userDaoBase " /></jpa:repositories> 

<bean id="userDaoBase" class="......."/>

此外,<jpa:repositories > 提供了一个 repository-impl-postfix 属性,用以指定实现类的后缀。如:

<jpa:repositories base-package="cn.wolfcode.spring_jdbc_jpa.dao"
repository-impl-postfix="Impl"/>

在框架扫描到 IUserDao 接口时,它将尝试在相同的包目录下查找 IUserDaoImpl.java,如果找到,便将其中的实现方法作为最终生成的代理类中相应方法的实现。

到此,Spring Data JPA的基本使用我们就先到这

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容