You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA中TicketRepository空指针异常排查求助

空指针异常原因分析及解决办法

问题描述

应用运行时抛出NullPointerException:无法调用com.Practice.PracticeProject.Repositories.TicketRepository.findAllByEmployeeID(int),因为ticketRepository为null,报错位置在Login.java第80行的AllMyTickets方法中。期望通过Spring JPA返回工单列表,但多次尝试注入TicketRepository均失败,运行时始终出现空指针异常。

相关代码

Login类代码

package com.Practice.PracticeProject.Service;

import com.Practice.PracticeProject.Model.Tickets;
import com.Practice.PracticeProject.Repositories.TicketRepository;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import java.security.Principal;
import java.util.List;

@Service
public class Login
{
    Authentication currentUser;

    public Login() { }

    public Login(Authentication currentUser)
    {
        this.currentUser = currentUser;
    }

    public String loggInUser(Principal principal, UserDetailsService userDetailsService)
    {
        UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName());

        if (userDetails != null)
        {
            System.out.println("Andre the current user is " + userDetails.getUsername());
            return userDetails.getUsername();
        }
        else
        {
            System.out.println("No current user");
            return "No Current User";
        }

    }

    public String currentUserInfo(Principal principal, UserDetailsService userDetailsService)
    {
        UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName());
        if (userDetails != null)
        {
            return userDetails.toString();
        }
        else
        {
            return "No Current User";
        }
    }

    public List<Tickets> AllMyTickets(int id, TicketRepository ticketRepository  )
    {
        List<Tickets> myTickets = ticketRepository.findAllByEmployeeID(id);
        if(myTickets.isEmpty())
        {
            System.out.println("Did not find any Tickets for given empoyeeid");
            System.exit(0);
        }
        return myTickets;
    }

}

TicketRepository类代码

package com.Practice.PracticeProject.Repositories;

import com.Practice.PracticeProject.Model.Tickets;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface TicketRepository extends JpaRepository<Tickets, Integer>
{
    @Query(nativeQuery = true,  value = "SELECT * FROM tickets  WHERE ticketid = :ticketid")
    List<Tickets> findAllByEmployeeID(@Param("ticketid") int ticketid);
}

异常原因

  1. 依赖注入方式错误:Login类的AllMyTickets方法通过参数接收ticketRepository,而非让Spring容器自动注入。调用该方法时若未传入有效的TicketRepository实例,必然导致空指针。Spring管理的Bean依赖应该通过类成员变量注入,而非方法参数传递。
  2. 构造器设计问题:Login类同时存在无参和带Authentication参数的构造器,Spring默认优先使用无参构造器创建实例,若未正确配置构造器注入,会影响其他依赖的初始化。
  3. Repository查询逻辑语义不符:findAllByEmployeeID方法名指向“按员工ID查询”,但原生SQL实际过滤的是ticketid字段,不仅逻辑混淆,还可能导致查询结果不符合预期。

解决办法

1. 修正依赖注入方式

将TicketRepository改为Login类的成员变量,通过构造器注入让Spring管理:

package com.Practice.PracticeProject.Service;

import com.Practice.PracticeProject.Model.Tickets;
import com.Practice.PracticeProject.Repositories.TicketRepository;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import java.security.Principal;
import java.util.List;

@Service
public class Login
{
    private final Authentication currentUser;
    private final TicketRepository ticketRepository;

    // 构造器注入所有依赖,移除无参构造器(或保留但确保Spring能正确处理)
    public Login(Authentication currentUser, TicketRepository ticketRepository)
    {
        this.currentUser = currentUser;
        this.ticketRepository = ticketRepository;
    }

    public String loggInUser(Principal principal, UserDetailsService userDetailsService)
    {
        UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName());

        if (userDetails != null)
        {
            System.out.println("Andre the current user is " + userDetails.getUsername());
            return userDetails.getUsername();
        }
        else
        {
            System.out.println("No current user");
            return "No Current User";
        }

    }

    public String currentUserInfo(Principal principal, UserDetailsService userDetailsService)
    {
        UserDetails userDetails = userDetailsService.loadUserByUsername(principal.getName());
        if (userDetails != null)
        {
            return userDetails.toString();
        }
        else
        {
            return "No Current User";
        }
    }

    public List<Tickets> AllMyTickets(int id)
    {
        List<Tickets> myTickets = ticketRepository.findAllByEmployeeID(id);
        if(myTickets.isEmpty())
        {
            System.out.println("Did not find any Tickets for given empoyeeid");
            // 替换System.exit(0),避免直接终止应用
            throw new RuntimeException("No tickets found for employee ID: " + id);
        }
        return myTickets;
    }

}

2. 修正Repository查询逻辑

让方法名与SQL过滤字段一致,若按员工ID查询,修改SQL为:

package com.Practice.PracticeProject.Repositories;

import com.Practice.PracticeProject.Model.Tickets;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface TicketRepository extends JpaRepository<Tickets, Integer>
{
    // 修正SQL,过滤employeeid字段
    @Query(nativeQuery = true,  value = "SELECT * FROM tickets WHERE employeeid = :employeeId")
    List<Tickets> findAllByEmployeeID(@Param("employeeId") int employeeId);

    // 可选:使用Spring Data JPA方法命名规则,无需原生SQL
    // List<Tickets> findByEmployeeId(int employeeId);
}

3. 确认组件扫描范围

确保Spring配置的组件扫描路径包含com.Practice.PracticeProject包,这样@Service和@Repository注解的类才能被正确识别并纳入Spring容器管理。

内容的提问来源于stack exchange,提问作者user13288376

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 17:34:50