spring cloud使用JpaRepository,dao层无法注入容器,调试报空指针的解决思路

     公司岗位调整,我从一个安卓开发转后台开发,以前在其他公司也接触过后台,那时公司用的是ssm框架,不过安卓还是
主业务,后台业务也只是略而兼之,并未深研,想着公司这次给机会做后台,本着技多不压身,就欣然接受,此时已经2019年了,微服务方兴未艾,如火如荼,自然我也就去学习微服务了,在学习过程中,spring cloud使用JpaRepository,编译是能通过,在调试接口时报了一个空指针,经过debug调试,是接口

public interface ProductInfoRepository extends JpaRepository<ProductInfo, String> {
   List<ProductInfo> findByProductStatus(List<String> productIdStatus);

}

 在下面的service中

@Service
public class ProductInfoServiceImpl implements IProductInfoService {
    @Autowired(required = false)
    private ProductInfoRepository productInfoRepository;

    @Override
    public List<ProductInfo> getProductList() {
      List<String> integerList = new ArrayList<>();
      integerList.add("1");
      List<ProductInfo> productInfoList = productInfoRepository.findByProductStatus(integerList);
      return productInfoList;
    }
}


      其中private ProductInfoRepository productInfoRepository是null的,ProductInfoRepository没有注入到容器中
调试几遍还是报空指针,只好求助百度,可以说困扰了我4天,都没有找到spring cloud使用JpaRepository报空指针的解决方案
网上找到的以下方案,都试了,都无用
1.private ProductInfoRepositoryproductInfoRepository是不是没有用@Autowired(required = false)注解,检查自己写的代码,是注解了
2.public interface ProductInfoRepository加上@Component,@Repository, 加上后,调试结果,service中的productInfoRepository还是为null,继续报空指针
3.controller和service中的方法是不是private的,检查自己的代码,方法都是public,排除该怀疑对象
4.entity实体类加上@table,@colum,调试结果,service中的productInfoRepository还是为null,报空指针
5.甚至自己怀疑是不是(required = false)了,去掉该配置,自然就报了另外一个异常,方案还是不对
6.Application上加上

@ComponentScan(basePackages = {"com.chengfeng.product.controller","com.chengfeng.product.service"}),
@EntityScan(basePackages = "com.chengfeng.product.entity")
@EnableJpaRepositories(basePackages = "com.chengfeng.product.repository")

即代码为


@SpringBootApplication()(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.chengfeng.product.controller","com.chengfeng.product.service"}),
@EntityScan(basePackages = "com.chengfeng.product.entity")
@EnableJpaRepositories(basePackages = "com.chengfeng.product.repository")
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }

}


上述加上,调试结果,service中的productInfoRepository还是为null,报空指针,
7.检查定义的entity实体类ProductInfo中的属性字段是否与数据库中一致,一一检查,都一一对应,排除该怀疑对象
8.当然什么重启了,清除缓存,说jar包冲突的,把原来的jar包全部清除重新下载,依然无用。
说实话,搞了几天都快崩溃了,放弃心又不甘,元气恢复,又鬼使神差继续调试。
9.是不是new service对象或者new  ProductInfoRepository对象了,检查自己的代码,也排除该怀疑对象
10.最后实在没有脾气了,把ProductInfoRepository定义的接口屏蔽掉,用JpaRepository原生生成的默认方法,还是报空指针。

最后,看了一眼ProductApplication 

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }
}


死马当活马医,把(exclude = DataSourceAutoConfiguration.class)去掉,将原来出现的

Error creating bean with name 'entityManagerFactory' defined in class path resource
 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]

异常暴露出来,把这个问题解决,看能不能顺便把空指针解决,然而运行后先报

HHH000342: Could not obtain connection to query metadata : Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, 
jdbc:mysql:http://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC

了一个新的问题,再报

 Exception encountered during context initialization - cancelling refresh attempt: 
 org.springframework.beans.factory.BeanCreationException:
 Error creating bean with name 'entityManagerFactory' defined in class path resource
 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: 
 Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException:
 Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]


 根据网上资料,application.properties中的spring.datasource.***肯定有问题,仔细看了几遍application.properties:

spring.application.name=product

server.port=8081
eureka.client.service-url.defaultZone: http://localhost:8761/eureka/

spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql:http://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = 123456

spring.jpa.hibernate.ddl-auto = update

# 方便jpa调试的配置
spring.jpa.show-sql = true

也没发现什么问题,最后经过对比,发现jdbc:mysql后面多了个http,之前没有开发配置过数据库,也不知这里到底如何配置,什么时候这里多了个http,难道是因为多了个http,抱着疑问的态度改成

spring.datasource.url= jdbc:mysql://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC


 奇迹出现了,项目成功运行起来,最后接口调试,service中的productInfoRepository也成功注入容器了了,接口也调通了,也不报空指针了。此刻我已经知道,肯定是ProductInfoRepository中的接口写的不符合jpa规范,所以才造成ProductInfoRepository不能成功注入容器,将原来的方法:

// List<ProductInfo> findByProductStatus(List<String> productIdStatus);


 放开,运行,果然是又报错,

@SpringBootApplication加上(exclude = DataSourceAutoConfiguration.class),运行项目,错误消失,接口调试,继续报空指针,
至于为什么这个方法造成jpa不能注入容器,想必是这种接口定义方法不符合jpa规范,jpa识别不了。

最终,spring cloud使用jpa,要避免Repository不能注入容器,防止空指针的发生,除了排除上述10点怀疑对象,还要注意以下3点:

(1)@SpringBootApplication不能加(exclude = DataSourceAutoConfiguration.class)

(2)application.properties中关于数据库的配置一定要准确

(3)继承JpaRepository的dao层接口中自己定义的方法一定要符合jpa规范,按jpa的提示定义相关防范,不要自己随意命名,

最后附上spring cloud demo的部分

pom.xml代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.chengfeng</groupId>
    <artifactId>product</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>product</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RC2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

application.properties代码:

spring.application.name=product

server.port=8081
eureka.client.service-url.defaultZone: http://localhost:8761/eureka/

spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = 123456

spring.jpa.hibernate.ddl-auto = update

# 方便jpa调试的配置
spring.jpa.show-sql = true
package com.chengfeng.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }

}

 controller层ProductController.java代码

package com.chengfeng.product.controller;


@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private IProductInfoService productInfoService;

    @GetMapping("/list")
    public void getProductList() {
        System.out.println("开始获取getProductList");
        //  1.查询所有商品
        List<ProductInfo> productInfoList = productInfoService.getProductList();
        System.out.println("获取的getProductList == ",productInfoList);

    }
}

Entity实体类ProductInfo.java代码

package com.chengfeng.product.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 这里表名会自动转换,数据库中驼峰会是下划线,下面的变量也是
 */

@Entity
public class ProductInfo {

    @Id
    private String productId;

    /** 名字. */
    private String productName;

    /** 单价. */
    private BigDecimal productPrice;

    /** 库存. */
    private Integer productStock;

    /** 描述. */
    private String productDescription;

    /** 小图. */
    private String productIcon;

    /** 状态, 0正常1下架. */
    private Integer productStatus;

    /** 类目编号. */
    private Integer categoryType;

    private Date createTime;

    private Date updateTime;

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public BigDecimal getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(BigDecimal productPrice) {
        this.productPrice = productPrice;
    }

    public Integer getProductStock() {
        return productStock;
    }

    public void setProductStock(Integer productStock) {
        this.productStock = productStock;
    }

    public String getProductDescription() {
        return productDescription;
    }

    public void setProductDescription(String productDescription) {
        this.productDescription = productDescription;
    }

    public String getProductIcon() {
        return productIcon;
    }

    public void setProductIcon(String productIcon) {
        this.productIcon = productIcon;
    }

    public Integer getProductStatus() {
        return productStatus;
    }

    public void setProductStatus(Integer productStatus) {
        this.productStatus = productStatus;
    }

    public Integer getCategoryType() {
        return categoryType;
    }

    public void setCategoryType(Integer categoryType) {
        this.categoryType = categoryType;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

dao层ProductInfoRepository.java代码

package com.chengfeng.product.repository;

import com.chengfeng.product.entity.ProductInfo;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ProductInfoRepository extends JpaRepository<ProductInfo, String> {
  List<ProductInfo> findByProductStatus(Integer productStatus);
}

服务层ProductInfoServiceImpl.java代码

package com.chengfeng.product.service;

import com.chengfeng.product.common.ProductStatusEnum;
import com.chengfeng.product.entity.ProductInfo;
import com.chengfeng.product.repository.ProductInfoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;


@Service
public class ProductInfoServiceImpl implements IProductInfoService {
    @Autowired(required = false)
    private ProductInfoRepository productInfoRepository;

    @Override
    public List<ProductInfo> getProductList() {
        List<ProductInfo> productInfoList = productInfoRepository.findByProductStatus(ProductStatusEnum.UP.getCode());
        return productInfoList;
    }
}

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值