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);
}
我正在使用 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);
}