spring-data-jpa编程中,方法参数的数据类型不一致引发的问题记录

一、代码结构

  • domain
    • model
      • BookDistributionRepository.java
  • infrastructure.persistence
    • jpa
      • BookDistributionRepositoryJPA.java
      • BookDistributionRepositoryJPAImpl.java

1、接口BookDistributionRepository.java

java 复制代码
public interface BookDistributionRepository {
    List<BookDistribution> findByBookIdAndStatus(String bookId, Short status);
}

2、BookDistributionRepositoryJPA.java

java 复制代码
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface BookDistributionRepositoryJPA  extends MongoRepository<BookDistribution, String>,
        QuerydslPredicateExecutor<BookDistribution>, BookDistributionRepository {
}

3、BookDistributionRepositoryJPAImpl.java

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import java.util.List;

public class BookDistributionRepositoryJPAImpl {

    @Autowired
    private MongoTemplate mongoTemplate;

    public Iterable<BookDistribution> findByBookIdAndStatus(String bookId, short status) {
        Criteria criteria = Criteria.where("bookId").is(bookId);
        if (status != null) {
            criteria.and("status").is(status);
        }
        return mongoTemplate.find(new Query(criteria), BookDistribution.class);
    }
}

二、现象总结

  • 1、程序启动的时候,报错BookDistributionRepository中的方法不符合命名规则,这里使用了jpa。
  • 2、即使按Jpa命名规范修改方法名后,程序启动正常,但是程序在断点调试的时候,不会进入方法的实现。

1、分析

  • 程序启动的时候就报错,除了指明方法不符合Jpa规范外,还有一个疑问必须解答。那就是我有对接口的方法进行重写。BookDistributionRepositoryJPAImpl.java有没有实例化呢?
  • 另外,第一个报错还说明接口中的方法并没有被真正重写!当然,我们先要去spring BeanFactory getBean()查看是否有实例化,具体见类org.springframework.beans.factory.support.AbstractBeanFactory。经断点调试跟踪,该类不仅实例化,且方法定义也是按我们所写。
  • 接下来,要解答为什么断点调试的时候,无法进入方法的实现。只能有一种解释:重写失败。(方法重写的要求是什么,)

1、方法名称相同:重写的方法名称必须与父类中的方法名称相同,包括方法的大小写和参数列表。
2、方法参数列表相同:重写的方法的参数列表(参数的数量、类型和顺序)必须与父类中的方法的参数列表相同。
3、方法返回类型兼容:重写的方法的返回类型必须与父类中的方法的返回类型兼容。这意味着子类的返回类型可以是父类方法返回类型的子类型(子类或接口类型)或者与其相同。如果是基本数据类型,返回类型必须相同。
4、访问修饰符不严格小于父类:重写的方法的访问修饰符不能比父类中的方法更严格。具体来说,如果父类方法是 public,子类方法可以是 public、protected 或 default(包内可见),但不能是 private。如果父类方法是 protected,子类方法可以是 protected 或 public,但不能是 default 或 private。
5、不能抛出更多异常:重写的方法不能抛出比父类方法更多或更宽的异常。子类方法可以不抛出异常,也可以抛出父类方法声明的异常或其子类异常,但不能抛出父类方法未声明的新异常。
6、不能使用 static 或 final 修饰符:重写的方法不能使用 static(静态方法)或 final(不能被重写的方法)修饰符。只有非 static 和非 final 的方法才能被重写。
7、必须是子类:方法重写只能在子类中进行,子类继承父类并重写父类方法。

对方法重写的要求还挺多,经过仔细对比,不难发现接口中的方法入参类型和重写的方法入参类型不一样。 前者是Short包装类型,而后者是基本数据类型short。

2、方法重写

修改实现方法的入参类型,和接口中的保持一致,也为包装类型Short。

程序启动成功,断点调试也能够进入重写方法里。

不仅如此,反过来,接口中的方法命名也不要求符合Jpa命名规范了。

也就是说,接口中的方法是要自定义实现的话,其命名规则是随意的,不受Jpa命名规范的约束。

三、以Impl结尾的java类为什么会被自动实例

注解@EnableJpaRepositories是在spring-data-jpa框架中,它有一个参数配置,叫repositoryImplementationPostfix,其值默认便是"Impl"。

spring-boot-autoconfigure框架有对其进行默认开启。

查看JpaRepositoriesRegistrar.java,默认有开启注解EnableJpaRepositories。

四、总结

通过本文也再次提醒我们,java是一个强类型的语言,作为方法重写这样的一个基础知识,对参数的类型可不能大意。

相关推荐
李慕婉学姐5 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆6 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin7 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20057 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉7 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国7 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882488 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈8 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_998 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹8 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理