(springBoot项目)SpringDataJpa的自定义Repository接口空指针异常

(一)自定义Repository空指针异常

在使用SpringDataJpa的时候,当自定义接口继承Repository或着其子接口之后,就测试会报接口空指针异常。
在这里插入图片描述
在这里插入图片描述

异常分析

1、NullPointerException说明UserRepository并没有被@Autowired所自动装配。而对引用自动装配的本质就是spring的IOC对bean的自动管理这里涉及到的对象其实是两个,一个是IOC容器,另一个是容器里的bean。如果自动装配失败,那必定是两者其中之一出了问题。
2、人话翻译过来就是:Ioc在不在?我要找他造个bean。
3、通过观察控制台可以发现,springboot项目根本就没启动,所以没有IOC。也就是你只执行了一个test类。

解决方案

在测试类Test类上加上两个注解,目的是启动springBoot获得IOC

  • @RunWith(SpringRunner.class)
  • @SpringBootTest(classes= springBoot项目启动入口 )
    在这里插入图片描述

结果

惊不惊喜,意不意外,喜提新异常UnsatisfiedDependencyException,哈哈哈哈哈哈哈哈哈哈哈哈嗝,
别走啊,IOC同志都来了,难道不再抢救一下?别着急往下看 [滑稽]

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.yellow.repository.UserRepositoryTest': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.yellow.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:364)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1268)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:384)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.yellow.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1097)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:583)
	... 29 more


(二)SpringDataJpa之UnsatisfiedDependencyException

上面说到IOC同志来了,并向你抛了一个异常,我选了一些关键的拿出来分析

org.springframework.beans.factory.UnsatisfiedDependencyException:Error creating bean with name 'com.yellow.repository.UserRepositoryTest': Unsatisfied dependency expressed through field 'userRepository';

异常分析

1、该异常的意思是,SpringIOC在制造UserRepositoryTest测试类的过程中,遇到了你要自动装配的UserRepository依赖不满足。
2、[人话版翻译] IOC说:这玩意UserRepository我这没有,我也不认识,没办法给你装到测试类上来
3、换句话说,要么就是你的UserRepository这个接口写的有问题,要么就是接口没有被spring所管理到,仔细检查你写的有没有问题,如果是没问题再往下

知识补充

Spring boot默认的扫描路径是启动类当前的包和子包,这很重要,是解决问题的关键。因为一般项目都是分层的,创建包时 有时候 会一时大意,没有归属到"启动包"下,就像我下面这样,因此默认状态下bean是不会被spring扫描到的。可以把包名改成启动类的子包或者在启动类加注解即可。
在这里插入图片描述

解决方案(二选一)

一、更改包名,使得所有包均为 “启动包” 的子包,如图。
在这里插入图片描述
二、在SpringBoot启动类中加@EnableJpaRepositories(basePackages = " ")注解,写上你自己repository的路径,保存再重新测试就OK了

@EnableJpaRepositories(basePackages = "com.yellow.repository")

关于注解的使用我就不啰嗦了,常用的扫描注解有{@EnableJpaRepositories、@EntityScan、@ComponentScan},不懂的同学自行百度或者查资料。
在这里插入图片描述

测试结果

测试通过,自定义repository接口不再为null

在这里插入图片描述

总结

上文两个部分讲的异常从本质上来讲,就是spring与bean之间的关系。
所谓的自动装配,其实是spring的IOC对bean的识别、生产、管理的过程。而我们程序猴要做的就是开发bean.class以及如何让bean被IOC的识别到,完成上述两步之后,即可在要使用bean的时候,通过@Autowired注解让IOC造一个bean拿过来用。

【人话版】:举个栗子,假设我们程序猴是个机械师,可以生产很多牛x机器。有一天心血来潮想造个高达,那造高达我们总需要一些工具对吧。比如锤子啊,但是市面上的锤子规格又太小了,造不了高达。那么我们就必须先把大锤子造出来。那我就很郁闷了,我想造的是高达,我不想花时间去造锤子,那怎么办呢?于是乎我就画了个 棒棒锤.jpeg,然后把它交给了锤子厂去生产,用它的时候我就找锤子厂拿。 这就解决问题了。

[类比]

  • 大前提:锤子厂 = spring.ioc
  • 图纸: 棒棒锤.jpeg = bean.class
  • 识别: 图纸交给工厂 = 让spring扫描到bean.class
  • 取物:交付锤子 = getBean或者@Autowired

我们要做的画图纸,交给工厂,拿来用即可。至于中间是怎么生厂出来,我们不管,这就是控制反转。如果bean装配失败,那么肯定是大前提、图纸、识别其中一步出了问题,将这三步对应到代码和配置即可排查。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
您好,感谢您的提问。创建一个 Spring Data JPA 的 Repository 接口非常简单,只需要按照以下步骤操作即可: 1. 创建一个继承自 `JpaRepository` 的接口,指定实体类和主键类型: ``` public interface UserRepository extends JpaRepository<User, Long> { } ``` 其中,`User` 是您的实体类,`Long` 是实体类的主键类型。`JpaRepository` 是 Spring Data JPA 提供的一个基础 Repository 接口,提供了一些基本的数据操作方法,如插入、删除、更新、查询等。 2. 在您的实体类上添加注解,指定表名和主键: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; // 省略 getter 和 setter 方法 } ``` 在上述代码中,`@Entity` 注解表示该类是一个 JPA 实体类,`@Table(name = "user")` 指定该实体类对应的数据库表名为 `user`,`@Id` 和 `@GeneratedValue` 注解指定实体类的主键。 3. 在您的 Spring Boot 应用程序中,使用 `@EnableJpaRepositories` 注解启用 Spring Data JPA,并指定 Repository 接口的包路径: ``` @SpringBootApplication @EnableJpaRepositories(basePackages = "com.example.repository") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 在上述代码中,`@EnableJpaRepositories` 注解用于启用 Spring Data JPA,`basePackages` 属性指定 Repository 接口的包路径。 4. 在您的服务层或控制器中注入 Repository 接口,即可使用 Spring Data JPA 提供的基本数据操作方法: ``` @RestController public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/users") public List<User> getAllUsers() { return userRepository.findAll(); } } ``` 在上述代码中,`@Autowired` 注解用于自动注入 `UserRepository` 对象,然后在 `getAllUsers` 方法中调用 `findAll` 方法获取所有用户信息。 通过上述步骤创建一个 Spring Data JPA 的 Repository 接口非常简单,希望能够帮助到您。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值