Issue
I'm making a small application using Spring Boot (and hibernate). I've encountered a strange problem while making this app, when I use my DAO object to save an object I've created to the database. It throws a null pointer exception and I haven't managed to figure out why, I've checked the usual suspect (DI) but I am using the annotation @autowired so it should work. I'm nearly tearing my hair out, maybe you'll see what it is that I've missed, thank you?
EDIT: I've followed the instructions posted by . and ., and it works but only if I comment out my deleteCategoryByName method. I've made some changes below, I've renamed the Demo1 class to LibraryApplication instead. I now get the error:
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 '!
My code
The 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);
}
The Domain-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;
}
}
The Service-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());
};
}
}
Picture of the table and column.
Solution
1.you should add a @Component
/ @Service
above CategoryService
2.you are not starting spring boot app correctly . you should do this instead of 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);
}
}
more on this can be found in https://spring.io/guides/gs/accessing-data-jpa/
answering your question directly , the reason your are getting NPE is because categoryDao
in CategoryService
is null , since you are not starting spring boot correctly.
P.S
you should note that having your app class (AccessingDataJpaApplication
) in a package "higher" in the hierarchy(library
package) then the rest of your components will make this work out of the book , otherwise you will have to mention the correct packages in the @SpringBootApplication
annotation
Answered By - asafb
Answer Checked By - Terry (JavaFixing Volunteer)