java.lang.Исключение NullPointerException при попытке извлечения объекта по идентификатору

#java #spring #hibernate #jpa #entity

#java #spring #спящий режим #jpa #объект

Вопрос:

Я использую spring и спящий режим.

Моя сущность:

 package com.igorgorbunov3333.core.entities.domain;

import com.igorgorbunov3333.core.entities.enums.Proceeding;

import javax.persistence.*;
import java.util.Date;

/**
 * Created by Игорь on 03.04.2016.
 */

@Entity
@Table(name = "cases")
@NamedQueries({
    @NamedQuery(name = "getAllCases", query = "SELECT c FROM Case c JOIN FETCH c.client JOIN FETCH c.firstInstance "  
            "JOIN FETCH c.secondInstance JOIN FETCH c.thirdInstance JOIN FETCH c.category")
})
public class Case {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "case_number")
    private String caseNumber;

    @ManyToOne
    @JoinColumn(name = "client_id")
    private Client client;

    @OneToOne
    @JoinColumn(name = "first_instance_id")
    private FirstInstance firstInstance;

    @OneToOne
    @JoinColumn(name = "second_instance_id")
    private SecondInstance secondInstance;

    @OneToOne
    @JoinColumn(name = "third_instance_id")
    private ThirdInstance thirdInstance;

    @Enumerated(EnumType.ORDINAL)
    private Proceeding proceeding;

    @Temporal(TemporalType.DATE)
    @Column(name = "closing_date")
    private Date closingDate;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;

    private float price;

    public long getId() {
        return id;
    }

    public String getCaseNumber() {
        return caseNumber;
    }

    public Client getClient() {
        return client;
    }

    public FirstInstance getFirstInstance() {
        return firstInstance;
    }

    public SecondInstance getSecondInstance() {
        return secondInstance;
    }

    public ThirdInstance getThirdInstance() {
        return thirdInstance;
    }

    public Proceeding getProceeding() {
        return proceeding;
    }

    public Date getClosingDate() {
        return closingDate;
    }

    public Category getCategory() {
        return category;
    }

    public float getPrice() {
        return price;
    }

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

    public void setCaseNumber(String caseNumber) {
        this.caseNumber = caseNumber;
    }

    public void setClient(Client client) {
        this.client = client;
    }

    public void setFirstInstance(FirstInstance firstInstance) {
        this.firstInstance = firstInstance;
    }

    public void setSecondInstance(SecondInstance secondInstance) {
        this.secondInstance = secondInstance;
    }

    public void setThirdInstance(ThirdInstance thirdInstance) {
        this.thirdInstance = thirdInstance;
    }

    public void setProceeding(Proceeding proceeding) {
        this.proceeding = proceeding;
    }

    public void setClosingDate(Date closingDate) {
        this.closingDate = closingDate;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public void setPrice(float price) {
        this.price = price;
    }
}
  

spring-config.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" >

    <!--@Transaction annotation support -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--Scanning components in base-package (look for annotations) -->
    <context:component-scan base-package="com.igorgorbunov3333"/>

    <!--Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired and so on-->
    <context:annotation-config/>

    <!--Обеспечивает работу с транзакциями в Spring -->
    <bean id="transactionManager"
          class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="emf"/>
    </bean>

    <!-- Datasource. Источник данных - база MySQL -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/database" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- EntityManagerFactory -->
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--Поставщик данных - hibernate-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <!--поиск сущностей в этом пакете-->
        <property name="packagesToScan"
                  value="com.igorgorbunov3333"/>
        <!--детали конфигурации поставщика постоянства (hibernate) -->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQL5Dialect
                </prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>


</beans>
  

Здесь я получаю исключение NullPointerException:

 public Case findById(long id) {
    return entityManager.find(Case.class, id);
}
  

Я уверен, что идентификатор правильный, но объект не может быть найден. Но когда я получаю все объекты, все в порядке:

 public List<Case> findAll() {
    Query query = entityManager.createNamedQuery("getAllCases");
    return query.getResultList();
}
  

В чем причина?

Полный трек NPE:

 09-Oct-2016 12:40:41.650 SEVERE [http-nio-8080-exec-7] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [ShowSingleCase] in context with path [] threw exception
 java.lang.NullPointerException
    at com.igorgorbunov3333.core.entities.service.impl.CaseServiceImpl.findById(CaseServiceImpl.java:32)
    at com.igorgorbunov3333.web.servlet.display.single.ShowSingleCase.doGet(ShowSingleCase.java:29)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1096)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:760)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
  

Мой CaseServiceImpl:

 package com.igorgorbunov3333.core.entities.service.impl;

import com.igorgorbunov3333.core.entities.domain.Case;
import com.igorgorbunov3333.core.entities.enums.CaseStatus;
import com.igorgorbunov3333.core.entities.service.api.CaseService;
import com.igorgorbunov3333.core.util.DateUtil;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.*;

/**
 * Created by Игорь on 27.07.2016.
 */

@Repository
@Service("CaseService")
public class CaseServiceImpl implements CaseService {

    @PersistenceContext
    private EntityManager entityManager;

    public Case findById(long id) {
        return entityManager.find(Case.class, id);
    }
}
  

Сервлет:

 package com.igorgorbunov3333.web.servlet.display.single;

import com.igorgorbunov3333.core.entities.domain.Case;
import com.igorgorbunov3333.core.entities.service.api.CaseService;
import com.igorgorbunov3333.core.entities.service.impl.CaseServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static com.igorgorbunov3333.web.util.Views.SINGLE_CASE_PAGE;

/**
 * Created by Игорь on 09.08.2016.
 */
@WebServlet(name = "ShowSingleCase", urlPatterns = "/showSingleCase")
public class ShowSingleCase extends HttpServlet {
    private CaseService caseService = new CaseServiceImpl();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        long id = Long.valueOf(request.getParameter("caseID"));
        Case c = caseService.findById(id);

        request.setAttribute("case", c);

        request.getRequestDispatcher(SINGLE_CASE_PAGE).forward(request, response);
    }
}
  

Комментарии:

1. У NPE есть трассировка стека. Итак, опубликуйте его

2. @Нил Стоктон, готово!

3. итак, как вы устанавливаете «EntityManager» в CaseServiceImpl?

4. @Нил Стоктон, мой вопрос обновлен!

5. Вы должны запросить у фреймворка экземпляр вашего класса CaseService, а не создавать его с new помощью . То, как вы это делаете, внедрение зависимостей entitymanager не выполняется, поэтому диспетчер объектов находится null в методе findById .

Ответ №1:

Ваша проблема в этой строке:

 private CaseService caseService = new CaseServiceImpl();
  

Это не то, как работает внедрение зависимостей. Вы создаете экземпляр своего объекта CaseService вручную. В этом случае фреймворк не будет вводить никаких зависимостей, поэтому ваше private EntityManager entityManager; поле будет null . Вместо этого вы должны аннотировать свое caseService поле @Autowired аннотацией. Это подскажет Spring ввести компонент из контекста:

 @Autowired
private CaseService caseService;
  

Ответ №2:

Единственное, что может быть null (не является примитивным) в указанной вами строке, что может вызвать проблему, — это EntityManager, поэтому вы ищете основную причину этого, которую я не вижу в опубликованном вами коде.

Комментарии:

1. Сбой find просто вернет null и не вызовет исключение, а примитивы не могут быть нулевыми. Кроме того, если параметр будет иметь значение null и это будет проблемой для find, исключение будет выдано из метода find .

Ответ №3:

Поскольку вы самостоятельно создаете объект класса CaseServiceImpl в своем классе сервлета, объект EntityManager не подключается автоматически spring, и именно по этой причине вы получаете исключение NullPointerException. либо вы должны автоматически подключить объект класса сервиса к классу сервлета, чтобы spring сам разрешил зависимость entitymanager и предоставил вам полностью настроенный объект service, либо вы должны установить объект entity manager в свой класс service при создании его объекта в servlet.