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

一、代码结构

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

在这里插入图片描述

在这里插入图片描述

1、接口BookDistributionRepository.java

public interface BookDistributionRepository {
    List<BookDistribution> findByBookIdAndStatus(String bookId, Short status);
}

2、BookDistributionRepositoryJPA.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


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是一个强类型的语言,作为方法重写这样的一个基础知识,对参数的类型可不能大意。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Data JPA 是基于 Spring 框架的一种数据访问技术,它简化了 JPA编程模型,提供了一种更加方便、高效的数据库操作方式。使用 Spring Data JPA,我们可以通过定义接口的方式,轻松地实现对数据库的增、删、改、查等操作。 下面是一个简单的 Spring Data JPA 的示例代码: 首先,我们需要定义一个实体类,如下所示: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Integer age; // 省略 getter 和 setter 方法 } ``` 接着,我们需要定义一个 Repository 接口,如下所示: ``` public interface UserRepository extends JpaRepository<User, Long> { } ``` 这里的 JpaRepository 是 Spring Data JPA 提供的一个接口,它包含了一些常用的数据库操作方法,例如:save、delete、findAll 等。我们只需要定义一个继承了 JpaRepository 的接口,并指定实体类和主键类型,就可以使用这些方法了。 最后,我们可以在代码使用 UserRepository,例如: ``` @Service public class UserService { @Autowired private UserRepository userRepository; public void saveUser(User user) { userRepository.save(user); } public List<User> findAllUsers() { return userRepository.findAll(); } } ``` 在这个示例代码,我们使用了 UserRepository 的 save 和 findAll 方法,分别实现了保存用户和查询所有用户的功能。 希望这个示例代码能够帮助你理解 Spring Data JPA 的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值