【问题标题】:Spring boot JPA deserialization problem when retrieving ID from other entity从其他实体检索ID时的Spring Boot JPA反序列化问题
【发布时间】:2020-10-17 06:02:30
【问题描述】:

我正在创建一个 Web 程序,以使用 spring boot、tomcat 和 JPA 映射存储占用级别。 我已经创建了成员模型/服务/控制器,当我尝试对其进行更新、创建、删除或从中获取信息时,它可以正常工作。

但也没有创建商店,当我使用 ownerId 创建商店时,我收到一条错误消息:

错误信息

[org.springframework.http.converter.HttpMessageNotReadableException:JSON 解析错误:无法构造com.project.so2.models.Member 的实例(尽管至少存在一个创建者):没有字符串参数构造函数/工厂方法可以从字符串值反序列化('1');嵌套异常是 com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造 com.project.so2.models.Member 的实例(尽管至少存在一个 Creator):没有从字符串值反序列化的字符串参数构造函数/工厂方法('1') 在 [来源:(PushbackInputStream); line: 4, column: 18] (通过引用链: com.project.so2.models.Store["owner_id"])]

我已经尝试查找类似的问题,但我没有看到任何适用的解决方案。

模型

商店

@Entity(name = "Store")
@Table(name = "store")
@SequenceGenerator(name = "store_id")
public class Store {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "store_id")
    @Column(name = "id")
    private long id;

    //many stores to one owner
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name = "owner_id", referencedColumnName = "id")
    private Member owner_id;
    
    //one store to many occupation level
    @OneToMany(mappedBy = "store")
    private List<Occupation> store_occupation;
    
    @OneToOne(mappedBy = "store")
    private Location location;

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

    @Column(name = "square_footage")
    private String square_footage;

    public Store() {
    }

会员

@Entity(name = "Member")
@Table(name = "member")
@SequenceGenerator(name = "member_id")
public class Member {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "member_id")
    @Column(name = "id")
    private long id;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "role")    
    private Role role;//customer|admin|store_owner
    
    @Column(name = "mail", unique = true)
    private String mail;
    
    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "owner_id")
    private List<Store> stores;
    
    
    
    /**
     * REALM to store passwords
     */
    
    @CreationTimestamp
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date createdAt;
    
    @UpdateTimestamp
    private Date updateAt;

存储控制器

@RestController
@RequestMapping("/store")
@ControllerAdvice()
@CrossOrigin
public class StoreController {
    @Autowired
    private StoreService storeservice;

    @PostMapping("/create")
    public ResponseEntity<HttpStatus> createStore(@RequestBody Store store) {
        try {
            this.storeservice.saveStore(store);
            return new ResponseEntity<>(HttpStatus.CREATED);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

商店服务

@Service
public class StoreService {
    
    @Autowired
    private StoreRepository storeRepository;//

    public void saveStore(Store store) {
        this.storeRepository.save(store); 
    }

请求负载:

{
    "name": "Pingo Azedo",
    "square_footage": "25m^2",
    "owner_id":{
        "member_id": "1"
    }
}

老实说,我不明白这个问题,也不知道如何解决它。如果有人可以提供帮助,将不胜感激!

【问题讨论】:

  • 可以发一下全班商店和会员吗?
  • 我刚刚做了,只是省略了 getter 和 setter @Hưng Chu
  • 你能贴出异常的堆栈跟踪吗?
  • 刚刚这样做了@YohanAloka
  • 这可能是请求负载的问题,您也可以发布请求负载吗?

标签: java json spring-boot jpa


【解决方案1】:

您正试图从 json 中反序列化成员,但杰克逊不知道如何仅使用“member_id”填写此成员,并且错误很明显是“找不到带有 String 的构造函数”。因此,为了获取成员 ID,您需要添加新的类请求 dto,例如:

String name;
String footage;
Long owner_id;

在您的控制器中使用您的新类,现在使用 owner_id,使用存储库在您的数据库中找到它,然后将其设置到您的商店。

【讨论】:

    【解决方案2】:

    您需要在有效负载中使用属性名称,而不是列名称。如下更改您的请求负载,

    {
      "name": "Pingo Azedo",
      "square_footage": "25m^2",
      "owner_id":{
           "id" : 1
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-16
      • 2014-09-10
      • 2018-02-05
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      • 2017-10-30
      相关资源
      最近更新 更多