返回顶部
首页 > 资讯 > 后端开发 > Python >Spring Boot JPA Repository之existsBy查询方法失效的解决
  • 522
分享到

Spring Boot JPA Repository之existsBy查询方法失效的解决

2024-04-02 19:04:59 522人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

引言: Spring Boot号称微服务的利器,在结合了spring Data与JPA之后,更是如虎添翼,开发快速的不像话,本文将讲述一个关于JPA中一个诡异问题的诊断分析过程以及修

引言: Spring Boot号称微服务的利器,在结合了spring Data与JPA之后,更是如虎添翼,开发快速的不像话,本文将讲述一个关于JPA中一个诡异问题的诊断分析过程以及修复方法。

环境介绍

jdk 1.8 Spring 4.2 Spring Boot 1.5.9

问题描述

在Spring Data中的Repository接口中创建了一个检查数据是否存在的接口方法:


@Repository
public interface VideoEntityRepository extends JpaRepository<VideoEntity, Long> {
    ........
    public boolean existsByUserIdAndName(long userId, String name);
   }

VideoEntity的类如下:


@SuppressWarnings("serial")
@Table(name="flook_video")
@Entity
@Data
@EqualsAndHashCode(callSuper=true)
public class VideoEntity extends BaseEntity {
    @Column(name="user_id")
    private long userId;
    @Column(name="name")
    private String name;
    @Column(name="change_version")
    private double changeVersion;
}

在调用方法existsBy方法的时候,返回的结果一直为false, 结果不正确,在偶的期望中,其执行结果应该不会出错的?那问题出在哪里呢?

关于existsBy的介绍

Spring Data提供了若干非常实用的扩展,将数据库表日常的CRUD操作都进行很好的实现,并提供了若干扩展机制,基于一套简单易用的命名规则,来基于声明式实现场景的数据库查询操作:


countByColumName
existsByColumnName

上述两种方式都是由Spring Data来帮助动态生成sql的。

基于@Query方式

除了基于countBy/existsBy两种方式之外,可以直接使用@Query方式来标注特定的SQL或者JPQL来实现功能,由于这种方式需要些SQL,功能上完全覆盖,但是工作量略大,不是最优的方式。

问题分析

由于底层使用了Hibernate/JPA/Spring Data来实现的数据访问层的实现,所以,最好的方式当然是查看动态生成的SQL了,于是找到了生成的SQL语句:


select videoentit0_.id as col_0_0_ from video videoentit0_ where videoentit0_.user_id=? and videoentit0_.name=? limit ?

表的名称是video,这个名称是不对的。这个情况是怎么发生的呢?

问题的解决

经过分析发现,是由于在代码中存在两个类名完全相同VideoEntity的类,虽然在Repository中我们的的确确没有引用错误相关的,问题应该出在当Spring Data碰到两个相同的类名之时,其实不知道如何来生成SQL的,换句话说,其应该是基于类名而非类路径来动态生成执行SQL的。

TODO: 基于源代码中找到相关部分内容。

问题解决

将当前的VideoEntity重新命名,确保不存在重名的问题,即使类的路径不一样,但是类名一样,也是会产生这样的问题。

从一个侧面来分析,在Spring Data中所有的DataBean都是需要使用全路径的类名的,否则同样会出现问题。

JpaRepository 查询规范

1.JpaRepository支持接口规范方法名查询

意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现,目前支持的关键字如下。

KeyWord

Sample

JPQL snippet

IsNotNull

findByAgeNotNull

... where x.age not null

Like

findByNameLike

... where x.name like ?1

NotLike

findByNameNotLike

... where x.name not like ?1

StartingWith

findByNameStartingWith

... where x.name like ?1(parameter bound with appended %)

EndingWith

findByNameEndingWith

... where x.name like ?1(parameter bound with prepended %)

Containing

findByNameContaining

... where x.name like ?1(parameter bound wrapped in %)

OrderBy

findByAgeOrderByName

... where x.age = ?1 order by x.name desc

Not

findByNameNot

... where x.name <> ?1

In

findByAgeIn

... where x.age in ?1

NotIn

findByAgeNotIn

... where x.age not in ?1

True

findByActiveTrue

... where x.avtive = true

Flase

findByActiveFalse

... where x.active = false

And

findByNameAndAge

... where x.name = ?1 and x.age = ?2

Or

findByNameOrAge

... where x.name = ?1 or x.age = ?2

Between

findBtAgeBetween

... where x.age between ?1 and ?2

LessThan

findByAgeLessThan

... where x.age < ?1

GreaterThan

findByAgeGreaterThan

... where x.age > ?1

After/Before

...

...

IsNull

findByAgeIsNull

... where x.age is null

2.JpaRepository相关查询功能

a.Spring DataJPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。

b.假如创建如下的查询:findByUserDepUuid(),框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为Doc。

1:先判断userDepUuid (根据POJO规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

2:从右往左截取第一个大写字母开头的字符串此处为Uuid),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设user为查询实体的一个属性;

3:接着处理剩下部分(DepUuid),先判断user所对应的类型是否有depUuid属性,如果有,则表示该方法最终是根据“Doc.user.depUuid” 的取值进行查询;否则继续按照步骤2的规则从右往左截取,最终表示根据“Doc.user.dep.uuid” 的值进行查询。

4:可能会存在一种特殊情况,比如Doc包含一个user的属性,也有一个userDep 属性,此时会存在混淆。可以明确在属性之间加上"_"以显式表达意图,比如"findByUser_DepUuid()"或者"findByUserDep_uuid()"

c.特殊的参数: 还可以直接在方法的参数上加入分页或排序的参数,比如:


Page<UserModel>findByName(String name, Pageable pageable);
List<UserModel>findByName(String name, Sort sort);

d.也可以使用JPA的NamedQueries,方法如下:

1:在实体类上使用@NamedQuery:


@NamedQuery(name ="UserModel.findByAge",query = "select o from UserModel
o where o.age >=?1")

2:在自己实现的DAO的Repository接口里面定义一个同名的方法,示例如下:


publicList<UserModel> findByAge(int age);

3:然后就可以使用了,Spring会先找是否有同名的NamedQuery,如果有,那么就不会按照接口定义的方法来解析。

e.还可以使用@Query来指定本地查询,只要设置nativeQuery为true,比如:


@Query(value="select* from tbl_user where name like %?1" ,nativeQuery=true)
publicList<UserModel> findByUuidOrAge(String name);

注意:当前版本的本地查询不支持翻页和动态的排序

f.使用命名化参数,使用@Param即可,比如:


@Query(value="selecto from UserModel o where o.name like %:nn")
publicList<UserModel> findByUuidOrAge(@Param("nn") String name);

g.同样支持更新类的Query语句,添加@Modifying即可,比如:


@Modifying
@Query(value="updateUserModel o set o.name=:newName where o.name like %:nn")
public intfindByUuidOrAge(@Param("nn") String name,@Param("newName")String
newName);

注意:

1:方法的返回值应该是int,表示更新语句所影响的行数

2:在调用的地方必须加事务,没有事务不能正常执行

f.创建查询的顺序

Spring Data JPA在为接口创建代理对象时,如果发现同时存在多种上述情况可用,它该优先采用哪种策略呢?

<jpa:repositories>提供了query-lookup-strategy 属性,用以指定查找的顺序。

它有如下三个取值:

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

2:create:通过解析方法名字来创建查询。即使有符合的命名查询,或者方法通过

@Query指定的查询语句,都将会被忽略

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: Spring Boot JPA Repository之existsBy查询方法失效的解决

本文链接: https://lsjlt.com/news/127984.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Spring Boot JPA Repository之existsBy查询方法失效的解决
    引言: Spring Boot号称微服务的利器,在结合了Spring Data与JPA之后,更是如虎添翼,开发快速的不像话,本文将讲述一个关于JPA中一个诡异问题的诊断分析过程以及修...
    99+
    2024-04-02
  • Spring Boot JPA Repository之existsBy查询方法失效怎么办
    小编给大家分享一下Spring Boot JPA Repository之existsBy查询方法失效怎么办,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!引言: S...
    99+
    2023-06-15
  • 继承jpa Repository 写自定义方法查询的实例分析
    这篇文章给大家介绍继承jpa Repository 写自定义方法查询的实例分析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。继承jpa Repository写自定义方法查询今天在写jpa查询的时候,...
    99+
    2023-06-21
  • 如何理解Spring Data JPA查询方式及方法名查询规则
    这篇文章给大家介绍如何理解Spring Data JPA查询方式及方法名查询规则,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Spring Data JPA查询方式及方法名查询规则Spring Da...
    99+
    2023-06-21
  • spring boot 使用Mybatis-plus查询方法解析
    目录前言普通查询批量查询条件查询前言 使用的数据库和相关代码见springboot整合mybatis plus与druid详情。使用test来进行使用: 普通查询 @Au...
    99+
    2024-04-02
  • 详解SpringDataJPA中Repository的接口查询方法
    目录1.查询方法定义详解2.搜索查询策略3.查询创建4.属性表达式5.特殊参数处理6.限制查询结果7. repository方法返回Collections or Iterables8...
    99+
    2024-04-02
  • 解决spring boot环境切换失效的问题
    目录spring boot环境切换失效概述解决springboot多环境配置文件无效springboot配置文件无效spring boot环境切换失效 概述 最近在使用-Dsprin...
    99+
    2024-04-02
  • Spring Data JPA实现动态查询的两种方法
    前言一般在写业务接口的过程中,很有可能需要实现可以动态组合各种查询条件的接口。如果我们根据一种查询条件组合一个方法的做法来写,那么将会有大量方法存在,繁琐,维护起来相当困难。想要实现动态查询,其实就是要实现拼接SQL语句。无论实现如何复杂,...
    99+
    2023-05-31
    spring data jpa
  • 详解Spring Data JPA动态条件查询的写法
    我们在使用SpringData JPA框架时,进行条件查询,如果是固定条件的查询,我们可以使用符合框架规则的自定义方法以及@Query注解实现。如果是查询条件是动态的,框架也提供了查询接口。JpaSpecificationExecutor...
    99+
    2023-05-31
    spring data jpa
  • spring boot整合mongo查询converter异常的方法
    这篇文章主要讲解了“spring boot整合mongo查询converter异常的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring boot整合mongo...
    99+
    2023-06-29
  • spring boot项目使用@JsonFormat失效问题的解决
    目录使用@JsonFormat失效原因:项目中配置了fastjson包使用@JsonFormat注解踩过的坑错误原因解决方案使用@JsonFormat失效 在实体类定义时间格式 原...
    99+
    2024-04-02
  • 解决mysql模糊查询索引失效问题的几种方法
    我们在使用like %通配符时常常会引起索引失效的问题。 这里,我们讨论一下like使用%的几种情况: 下列例子用到的索引(VC_STUDENT_NAME) 一、like ‘xx...
    99+
    2024-04-02
  • SpringBoot JPA懒加载失效的解决方案(亲测有效)
    SpringBoot JPA懒加载失效 使用springBoot JPA 对两个实体类进行双向关联,并设置了懒加载,如下: 然后在查询后用到了roles,会报错, 解决办法如下:...
    99+
    2024-04-02
  • Springboot的spring-boot-maven-plugin导入失败的解决方案
    Springboot spring-boot-maven-plugin导入失败 因为之前换了本地仓库,再打开项目的时候就变成红色了,问题是其他依赖都导好了,只有这个家伙红的刺眼。 找...
    99+
    2024-04-02
  • Spring接口方法加@Transactional失效如何解决
    这篇文章主要介绍了Spring接口方法加@Transactional失效如何解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring接口方法加@Transactional失效如何解决文章都会有所收获,下面...
    99+
    2023-07-05
  • mysql进行查询缓存失败的解决方法
    小编给大家分享一下mysql进行查询缓存失败的解决方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.配置参数MySQL的查询缓存默认是关闭的,需要手动配置参数...
    99+
    2023-06-14
  • Spring @Cacheable注解类内部调用失效的解决方法
    这期内容当中小编将会给大家带来有关Spring @Cacheable注解类内部调用失效的解决方法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。@Cacheable注解类内部调用失效如果你只是想使...
    99+
    2023-06-22
  • spring boot security设置忽略地址不生效的解决方法
    这篇文章主要讲解了“spring boot security设置忽略地址不生效的解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring boot security设置忽略地址不生...
    99+
    2023-06-20
  • Spring事务管理下synchronized锁失效问题的解决方法
    目录一、我的思考二、图解出现的原因三、解决问题总结最近看到一个技术技术问题:synchronized锁问题? 开启10000个线程,每个线程给员工表的money字段【初始值是0】加1...
    99+
    2024-04-02
  • Mysql索引失效的解决方法
    小编给大家分享一下Mysql索引失效的解决方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!背景6千万数据量的数据表出现了一个满...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作