Java - Spring Boot - Hibernate - JPA(@ManyToOne 发布错误)

Posted

技术标签:

【中文标题】Java - Spring Boot - Hibernate - JPA(@ManyToOne 发布错误)【英文标题】:Java - Spring Boot - Hibernate - JPA (Error with post @ManyToOne) 【发布时间】:2021-07-26 22:36:30 【问题描述】:

我有两个模型,一个给客户,一个给卖家,在客户表中我只需要一个卖家,已经在卖家表中,我可以为一个卖家有多个客户。

但是当我尝试添加新客户并设置销售人员的 ID 时,它就不起作用了。

代码如下:

卖家型号:

    package com.crud.spring.jpa.postgresql.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.*;
    
    @Entity
    @AllArgsConstructor
    @Getter
    @Setter
    @Table(name = "sellers", uniqueConstraints = @UniqueConstraint(columnNames = "code"))
    public class Seller 
    
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
    
      @Column(name = "code")
      private long code;
    
      @Column(name = "name")
      private String name;
    
      public Seller()
      
    

客户端模型:

    package com.crud.spring.jpa.postgresql.model;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    import org.hibernate.annotations.OnDelete;
    import org.hibernate.annotations.OnDeleteAction;
    
    import javax.persistence.*;
    
    @Entity
    @AllArgsConstructor
    @Getter
    @Setter
    @Table(name = "clients", uniqueConstraints = @UniqueConstraint(columnNames = "code"))
    public class Client 
    
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long id;
    
      @Column(name = "code")
      private long code;
    
      @Column(name = "name")
      private String name;
    
      @ManyToOne(fetch = FetchType.LAZY, optional = false)
      @JoinColumn(name = "seller_id", referencedColumnName = "id", nullable = false)
      @OnDelete(action = OnDeleteAction.CASCADE)
      @JsonIgnore
      private Seller seller;
    
      public Client()
      
    

客户端控制器:

    @PostMapping("/clients")
    public ResponseEntity createClients(@RequestBody Client client) 
      return this.service.createClients(client);
    

客户服务:

    public ResponseEntity createClients(Client client) 
      try 
        client = this.repository.save(client);
    
        return new ResponseEntity(client, HttpStatus.OK);
       catch (Exception e)
        return new ResponseEntity(e, HttpStatus.INTERNAL_SERVER_ERROR);
      
    

后卖家:

发布客户:

错误是:

"entityName": "com.crud.spring.jpa.postgresql.model.Client", "propertyName": "seller", "message": "not-null property references a 空值或瞬态值: com.crud.spring.jpa.postgresql.model.Client.seller", "localizedMessage": "非空属性引用空或瞬态 值:com.crud.spring.jpa.postgresql.model.Client.seller", "suppressed": [] "message": "not-null 属性引用了一个 null 或 瞬态值:com.crud.spring.jpa.postgresql.model.Client.seller; 嵌套异常是 org.hibernate.PropertyValueException: not-null 属性引用空值或瞬态值: com.crud.spring.jpa.postgresql.model.Client.seller", enter code here"localizedMessage": "not-null 属性引用了 null 或 瞬态值:com.crud.spring.jpa.postgresql.model.Client.seller; 嵌套异常是 org.hibernate.PropertyValueException: not-null 属性引用空值或瞬态值: com.crud.spring.jpa.postgresql.model.Client.seller",

【问题讨论】:

【参考方案1】:

尝试使用 json "seller":"id":15 insted of "seller_id":15

【讨论】:

不要这样做。我如何这样工作: "code": 1, "name": "Eduardo", "seller_id": 15 "code": 1, "name": "Eduardo","seller":"id":15 你应该这样尝试,因为当你引用卖家时,你引用了一个你会通过它的 id 找到的类 我设法改善了帖子中代码的可视化,您可以再检查一下吗?【参考方案2】:

所以,有一些更正: 当您的有效载荷包含现有卖家的 id 时:

    使用有效负载发送现有卖家 ID

    "code" : 216,
    "name" : "addclientforseller5",
    "seller" :
        
            "id" : 5
           


    在您的服务实现中添加此代码

    public Client createClients(Client client) 
        Long sellerId = client.getSeller().getId();
        Optional<Seller> existingSeller = sellerRepository.findById(sellerId);
        if (existingSeller.isPresent()) 
            Seller savedSellerObject = existingSeller.get();
            client.setSeller(savedSellerObject);
         else 
            // throw exception
        

        return clientSellerRepository.save(client); // you can return ResponseEntity also
    

当您的有效负载包含卖家对象以创建新卖家时,请执行以下操作:

    有效负载应如下所示

    "code" : 112,
    "name" : "Pure",
    "seller" :
        "code" : 1111,
        "name" : "Guava"
    

    将此代码添加到您的服务实现中
    @Autowired
    ClientRepository clientRepository;

    @Autowired
    SellerRepository sellerRepository;

public Client createClients(Client client) 
        Seller seller = new Seller();
        seller.setCode(client.getSeller().getCode());
        seller.setName(client.getSeller().getName());
        Seller savedSeller = sellerRepository.save(seller);
        client.setSeller(savedSeller);
        return clientRepository.save(client);
    
    从客户端类的卖方字段中删除 @JsonIngnore。
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "seller_id", referencedColumnName = "id")
    @OnDelete(action = OnDeleteAction.CASCADE)
    //@JsonIgnore
    private Seller seller;

【讨论】:

不要这样做。我该如何工作:``` "code": 1, "name": "Eduardo", "seller_id": 15 `` 无法在有效负载中按照您的意愿发送请求。 我设法改进了帖子中代码的可视化,您可以再检查一下吗? 好的。如果我的回答解决了您的问题。请投票。 我不能只引用 ID 而不是客户端中的整个卖家对象吗?【参考方案3】:

我已经模拟了您的代码并有以下观察结果以使其正常工作。

从客户端模型中移除 @JsonIgnore 注解 Jpa 基于对象引用而不是单独的值工作。因此,您可能需要修改客户端服务代码。
 try 
           Optional<Seller> seller = sellerRepository.findById(client.getSeller().getId());
           if(seller.isPresent())
               client.setSeller(seller.get());
               client = this.repository.save(client);
           
            return new ResponseEntity(client, HttpStatus.OK);
         catch (Exception e) 
            return new ResponseEntity(e, HttpStatus.INTERNAL_SERVER_ERROR);
        

在上面的代码中,我们使用请求客户端模型中的卖家 ID 并从 db 中获取卖家对象。然后我们设置对客户端模型的引用。

为 createClient 传递 Json 输入,如图所示

    "id": 1,
    "code": 2,
    "name": "Client_1",
    "seller": 
        "id": 1
    

注意:您必须先创建一个有效的卖家,然后才能通过传递卖家 ID 创建客户端。

【讨论】:

以上是关于Java - Spring Boot - Hibernate - JPA(@ManyToOne 发布错误)的主要内容,如果未能解决你的问题,请参考以下文章

Java相关面试题总结+答案

关于Spring-Data-Jpa的一些理解

SpringBoot入门 数据库访问之spring data jpa

Spring Boot 各版本的Java版本要求

Spring Boot . 2 -- 用Spring Boot 创建一个Java Web 应用

如何 JUnit 测试 Spring-Boot 的 Application.java