Java Spring 引导 JPA - 保存到数据库时抛出 NullPointer 异常

Java Spring Boot JPA - Throws NullPointer Exception when saving to database

我正在使用 Spring 引导(和休眠)制作一个小应用程序。当我使用我的 DAO 对象将我创建的对象保存到数据库时,我在制作这个应用程序时遇到了一个奇怪的问题。它抛出一个空指针异常,我还没有弄清楚为什么,我已经检查了通常的可疑对象 (DI),但我正在使用注释 @autowired,所以它应该可以工作。我差点把头发扯掉,也许你会明白我错过了什么,谢谢?

编辑:我已按照 发布的说明进行操作。和 ., 它有效,但前提是我注释掉我的 deleteCategoryByName 方法。我在下面做了一些更改,我将 Demo1 class 重命名为 LibraryApplication。我现在得到错误:

ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'categoryService': Unsatisfied dependency expressed through field 'categoryDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'categoryDao': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Using named parameters for method public abstract java.lang.Void consid.programmeringstest.library.dao.CategoryDao.deleteCategoryByName(java.lang.String) but parameter 'Optional[categoryName]' not found in annotated query 'DELETE FROM category WHERE name = :category_name '!

我的代码

DAO-class

package library.dao;

import library.domain.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


public interface CategoryDao extends JpaRepository<Category, Long> {
    default Category findByIdOrThrow(Long id) {
        return findById(id).orElseThrow();
    }
    
    @Modifying
    @Query("DELETE FROM category WHERE name = :category_name ")
    public void deleteCategoryByName(@Param("categoryName") String categoryName);
}

领域-class

package library.domain;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Category implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String categoryName;
    
    public Category() {
    }
    
    public Category(String name) {
        this.categoryName = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCategoryName() {
        return categoryName;
    }

    public void setCategoryName(String name) {
        this.categoryName = name;
    }
    
}

服务-class

package library.service;

import library.dao.CategoryDao;
import library.domain.Category;
import org.springframework.beans.factory.annotation.Autowired;


public class CategoryService {
    
    @Autowired
    private CategoryDao categoryDao;
    
    public Category createCategory() {
        Category result = new Category();
        return categoryDao.save(result);
    }
    
    public Category createCategory(String name) {
        Category result = new Category(name);
        return categoryDao.save(result);
    }
    
    public void deleteCategoryByName(String name) {
        categoryDao.deleteCategoryByName(name);
    }
    
}

package library;

import library.dao.CategoryDao;
import library.domain.Category;
import library.service.CategoryService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableAutoConfiguration
public class LibraryApplication {
    public static void main(String[] args) {
        SpringApplication.run(LibraryApplication.class, args);
    }
    
  @Bean
  public CommandLineRunner demo(CategoryDao categoryDao) {
    return (args) -> {
        categoryDao.save(new Category("Test"));
        Category category = categoryDao.findByIdOrThrow(1);
        System.out.println(category.getCategoryName());
    };
  }
}

table 和专栏的图片。

首先你需要添加的是 @SpringBootApplication 到主要的 class。第二 - SpringApplication.run(Demo1.class, args); 在 main(executable) 方法的第一行。另外,不要忘记将 @Service 添加到应用程序的服务 class 中。

1.you 应该在 CategoryService

上面加一个 @Component / @Service

2.you 未正确启动 spring 启动应用程序。你应该这样做而不是 Demo1:

package library;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AccessingDataJpaApplication {

  public static void main(String[] args) {
    SpringApplication.run(AccessingDataJpaApplication.class, args);
  }

}

有关此内容的更多信息,请参阅 https://spring.io/guides/gs/accessing-data-jpa/

直接回答您的问题,您获得 NPE 的原因是因为 CategoryService 中的 categoryDao 为空,因为您没有 spring 正确启动。

P.S

您应该注意,将您的应用程序 class (AccessingDataJpaApplication ) 放在层次结构中“更高”的包中(library 包),然后您的其余组件将使这个根据书本工作,否则您将不得不在 @SpringBootApplication 注释

中提及正确的包

您的 DAO class 参数名称不正确 categoryName。应该是category_name。并且还使用 saveAndFlush() 而不仅仅是 save()

CategoryDao.java

package library.dao;

import library.domain.Category;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


public interface CategoryDao extends JpaRepository<Category, Long> {
    default Category findByIdOrThrow(Long id) {
        return findById(id).orElseThrow();
    }
    
    @Modifying
    @Query("DELETE FROM category WHERE name = :category_name ")
    public void deleteCategoryByName(@Param("category_name") String categoryName);
}