【问题标题】:Why my programme return NullPointerException [duplicate]为什么我的程序返回 NullPointerException [重复]
【发布时间】:2022-01-16 07:04:51
【问题描述】:

我正在开发 Spring 的库存管理应用程序。 我有一个创建发票(事实)的函数,它使用客户(客户)的 ID 创建发票,其中我还有一个创建发票详细信息的函数。 这是我的实体:

发票实体:

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Facture implements Serializable {
    
    public Facture(float d, float e, Date date, boolean b, Set<DetailFacture> detailFactures2, Client c1) {
        // TODO Auto-generated constructor stub
    }

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name="idFacture")
    private Long idFacture;
    @Column(name="montantRemise")
    private  float  montantRemise;
    @Column(name="montantFacture")
    private  float  montantFacture;
    @Temporal(TemporalType.DATE)
    @Column(name="dateFacture")
    private Date dateFacture;
    @Column(name="active")
    private boolean active;
    
    @OneToMany(mappedBy="facture")
    @JsonIgnore
    private Set<DetailFacture> detailFactures;
    
    @ManyToOne
    @JsonIgnore
    private Client client;
    
}

发票详细信息实体:

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class DetailFacture implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name="idDetailFacture")
    private Long idDetailFacture;
    @Column(name="qte")
    private  float  qte;
    @Column(name="prixTotal")
    private  float  prixTotal;
    @Column(name="pourcentageRemise")
    private int pourcentageRemise;
    @Column(name="montantRemise")
    private int montantRemise;
    
    @ManyToOne
    @JsonIgnore
    private Produit produit;
    
    @ManyToOne
    @JsonIgnore
    private Facture facture;

    
}

客户实体:

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Client implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name="idClient")
    private Long idClient;
    @Column(name="nom")
    private String nom;
    @Column(name="prenom")
    private String prenom;
    @Temporal(TemporalType.DATE)
    @Column(name="dateNaissance")
    private Date dateNaissance;
    @Column(name="email")
    private String email;
    @Column(name="password")
    private String password;
    @Column(name="categorieClient")
    private CategorieClient categorieClient;
    @Column(name="profession")
    private Profession profession;
    
    @OneToMany(mappedBy="client")
    private List<Facture> factures;

    
}

这是我在发票服务中创建带有客户 ID 的发票的函数:

@Override
    @Transactional
    public Facture addFactureClient(Facture f, Long idClient) {
        // TODO Auto-generated method stub
        Client client = clientRepository.findById(idClient).orElse(null);
        f.setClient(client);
        f.setDateFacture(new Date());
        f.setActive(true);
        Set<DetailFacture> detailfactures = f.getDetailFactures();
        Facture facture = addDetailFacture(f, detailfactures);
        return factureRepository.save(facture);
    }

这是创建发票详细信息的函数:

private Facture addDetailFacture(Facture f, Set<DetailFacture> detailfactures){
        float montantFacture = 0;
        float montantRemise = 0;
        System.out.println(detailfactures);
        for (DetailFacture detail : detailfactures){
            Produit produit = produitRepository.findById(detail.getProduit().getIdProduit()).orElse(null);
            float prixTotalDetail = detail.getQte() * produit.getPrixUnitaire();
            float montantRemiseDetail = (prixTotalDetail * detail.getPourcentageRemise())/100;
            float prixTotalDetailRemise = prixTotalDetail - montantRemiseDetail;
            detail.setMontantRemise((int)montantRemiseDetail);
            detail.setPrixTotal(prixTotalDetailRemise);
            montantFacture = montantFacture + prixTotalDetailRemise;
            montantRemise = montantRemise + montantRemiseDetail;
            detail.setProduit(produit);
            detail.setFacture(f);
            detailFactureRepository.save(detail);
        }
        f.setMontantFacture(montantFacture);
        f.setMontantRemise(montantRemise);
        return f;
    }

这是我控制器中的功能:

    @ApiOperation(value = "Ajouter facture avec client")
    @PostMapping("/add-facture/{idClient}")
    @ResponseBody
    Facture addFacture(@RequestBody Facture f, @PathVariable("idClient") long idClient) {
        return factureService.addFactureClient(f, idClient);
    }

这就是我使用邮递员进行测试的方式:

问题是,当我创建新发票时,它会在这一行返回 NullPointerException:

Facture facture = addDetailFacture(f, detailfactures);

为什么detailfactures返回null?

【问题讨论】:

  • 该行不会导致空指针异常。方法addDetailFacture 中的一行可以,但不是这个调用本身。使用调试器并逐步检查代码以检查哪个变量为空。
  • 请始终添加完整的堆栈跟踪。没有它是不可能的帮助
  • 如果猜测detailfactures 为空,这就是for (DetailFacture detail : detailfactures){ 抛出NullPointerException 的原因
  • 为什么 detailfactures 返回 null? 因为它不在你的 rquest 结构中
  • 我在邮递员中更改了这样的请求:{ "detailFactures":{ "qte": 3.0, "pourcentageRemise": 20, "produit":{ "idProduit":1 } } } 但它同样的问题

标签: spring-boot postman


【解决方案1】:

这是你有问题的方法

private Facture addDetailFacture(Facture f, Set<DetailFacture> detailfactures){
        float montantFacture = 0;
        float montantRemise = 0;
        System.out.println(detailfactures);
        for (DetailFacture detail : detailfactures){
            Produit produit = produitRepository.findById(detail.getProduit().getIdProduit()).orElse(null);
            float prixTotalDetail = detail.getQte() * produit.getPrixUnitaire();
            float montantRemiseDetail = (prixTotalDetail * detail.getPourcentageRemise())/100;
            float prixTotalDetailRemise = prixTotalDetail - montantRemiseDetail;
            detail.setMontantRemise((int)montantRemiseDetail);
            detail.setPrixTotal(prixTotalDetailRemise);
            montantFacture = montantFacture + prixTotalDetailRemise;
            montantRemise = montantRemise + montantRemiseDetail;
            detail.setProduit(produit);
            detail.setFacture(f);
            detailFactureRepository.save(detail);
        }
        f.setMontantFacture(montantFacture);
        f.setMontantRemise(montantRemise);
        return f;
    }

NPE (NullPointerException) 在您的代码尝试引用数据成员或调用 null 对象的方法时发生。

在您的情况下,null 可能是什么:

  • detailfactures
  • produitRepository
  • detail
  • detail.getProduit()
  • produitRepository.findById(detail.getProduit().getIdProduit())
  • detail
  • produit
  • detail.getPourcentageRemise()
  • f

为了从这些候选人中找出null 是什么,您需要调试您的应用程序或查看详细的错误消息以找出是哪一行抛出了null。一旦找到,您就会知道null 是什么,您将有以下选择:

  • 您可以首先找出原因是null 并修复导致问题的代码块
  • 您可以try-catch 并使用一些特殊的错误处理代码来处理null 情况

【讨论】:

  • detailfactures 是返回 null 但我不知道为什么?
  • @KhalilFathalli 你的Set&lt;DetailFacture&gt; detailfactures = f.getDetailFactures(); 行是罪魁祸首。可能是您的数据库中有一个带有 null 作为值的外键。
  • 你是对的 f.getDetailFactures() 返回 null 但在我的数据库中我没有带 null 的外键
  • @KhalilFathalli 也许你的 Facture 没有补水。
  • 我该如何解决这个问题_
猜你喜欢
  • 2020-07-05
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 2015-01-12
  • 2016-09-10
  • 2021-01-03
相关资源
最近更新 更多