HttpMessageNotWritableException:无法写入 JSON:将数据添加到数据库后无法初始化代理



这是我的问题。在我从 POSTMAN 发送POST请求以在 SQL 数据库中创建/添加行后,我无法编写 JSON。我需要服务器发回添加条目的响应,以便检索SQL生成的ID。

当新的Case条目是两个实体(UserApplication(的子项和一个实体(Owner(的孙子时,我会遇到这个问题。

*User(Owner)
|
| *Application
|/ 
*Case

我是新手,目前正在使用 Spring Boot JPA 软件包。

我知道很多人都问过与上述错误有关的问题。据我所知,没有关于我的案子。所有这些都是指通过 HTTPGET方法进行的修复。如果你发现了一些,请引导我去找他们。或者请帮助回答我的查询。任何帮助不胜感激!

我在这里附上我的代码:

用户实体

package com.lightlce.CRUD.Entities;
import javax.persistence.*;
@Entity(name = "User")
@Table(name = "User", schema = "dbo")
public class User {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String staffId;
private String username;
private String role;
public User (){}
public User(Integer id, String staffId, String username, String role) {
this.id = id;
this.staffId = staffId;
this.username = username;
this.role = role;
}
// Getters and Setters
}

应用程序实体

package com.lightlce.CRUD.Entities;
import javax.persistence.*;
@Entity(name = "Application")
@Table(name = "InvApplication", schema = "dbo")
public class Application {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String applicationName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ownerId")
private User owner;
public Application(){}
public Application(Integer id, String applicationName, User owner) {
this.id = id;
this.applicationName = applicationName;
this.owner = owner;
}
// Getters and Setters
}

案例实体

package com.lightlce.CRUD.Entities;
import com.lightlce.CRUD.AuditModel.Auditable;
import javax.persistence.*;
@Entity(name = "Case")
@Table(name = "InvCase", schema = "dbo")
public class Case extends Auditable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userId")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "applicationId")
private Application application;
//redacted
public Case() {
}
public Case(Integer id, User user, Application application) {
this.id = id;
this.user = user;
this.application = application;
}
// Getters and Setters
}

案例控制器

package com.lightlce.CRUD.Controllers;
import com.lightlce.CRUD.Entities.Application;
import com.lightlce.CRUD.Entities.Case;
import com.lightlce.CRUD.Entities.User;
import com.lightlce.CRUD.Repository.ApplicationRepository;
import com.lightlce.CRUD.Repository.CaseRepository;
import com.lightlce.CRUD.Repository.UserRepository;
import com.lightlce.CRUD.Services.ApplicationService;
import com.lightlce.CRUD.Services.CaseService;
import com.lightlce.CRUD.Services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@RestController
public class CaseController {
@Autowired
private CaseService caseService;
@Autowired
private UserService userService;
@Autowired
private ApplicationRepository applicationRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private CaseRepository caseRepository;
@Autowired
private UserController userController;
@RequestMapping("cases")
public Page<Case> getAllCases(Pageable pageable) {
return caseService.getAllCases(pageable);
}
@PostMapping("cases/add")
public Case addCase(@RequestBody Case aCase) {
User staff = userService.searchUser(aCase.getUser()); //Finds the user based on ID provided
Application application = applicationRepository.findById(aCase.getApplication().getId()).get(); //Finds the application based on ID provided
aCase.setUser(staff);
aCase.setApplication(application);
return caseService.addCase(aCase);
}
}

案例服务

package com.lightlce.CRUD.Services;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.lightlce.CRUD.Entities.Application;
import com.lightlce.CRUD.Entities.Case;
import com.lightlce.CRUD.Entities.User;
import com.lightlce.CRUD.Repository.CaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service
public class CaseService {
@Autowired
private CaseRepository caseRepository;
@Autowired
private UserService userService;
public Page<Case> getAllCases(Pageable pageable){
return caseRepository.customFindAll(pageable);
}
public Case addCase(Case aCase) {
caseRepository.save(aCase);
return aCase;
}
}

案例库

package com.lightlce.CRUD.Repository;
import com.lightlce.CRUD.Entities.Case;
import com.lightlce.CRUD.Entities.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@Repository
public interface CaseRepository extends JpaRepository<Case, Integer>{
Page<Case> findAll(Pageable pageable);
@Query(value = "SELECT c FROM com.lightlce.CRUD.Entities.Case c " +
"JOIN FETCH c.user u " +
"JOIN FETCH c.application a " +
"JOIN FETCH a.owner o",
countQuery = "SELECT COUNT(c) FROM  com.lightlce.CRUD.Entities.Case c " +
"JOIN c.user u " +
"JOIN c.application a " +
"JOIN a.owner o")
Page<Case> customFindAll(Pageable pageable);
}

发布 http://localhost:8080/cases/add

{
"user": {
"staffId": "TEST123"
},
"application":{
"id": 2
}
}

预期响应

{
"created_at": "2020-05-13T09:34:04.093+0000",
"modified_at": "2020-05-13T09:34:04.093+0000",
"id": 1
"user": {
"id": 1,
"staffId": "TEST123",
"username": "lightlce",
"role": "admin"
},
"application": {
"id": 2,
"applicationName": "ApplicationDemo",
"owner": {
"id": 1,
"staffId": "TEST123",
"username": "lightlce",
"role": "admin"
}
}
}

邮递员例外

{
"timestamp": "2020-05-14T02:36:40.999+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Could not write JSON: could not initialize proxy [com.lightlce.CRUD.Entities.User#2] - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy [com.lightlce.CRUD.Entities.User#2] - no Session (through reference chain: com.lightlce.CRUD.Entities.Case["application"]->com.lightlce.CRUD.Entities.Application["owner"]->com.lightlce.CRUD.Entities.User$HibernateProxy$QRpaILkJ["staffId"])",
"path": "/cases/add"
}

春季引导日志

2020-05-14 10:36:38.262 DEBUG 50878 --- [nio-8080-exec-6] org.hibernate.SQL                        : 
select
user0_.id as id1_0_,
user0_.role as role2_0_,
user0_.staffId as staffId3_0_,
user0_.username as username4_0_ 
from
dbo.InvAllUser user0_ 
where
user0_.staffId=?
Hibernate: 
select
user0_.id as id1_0_,
user0_.role as role2_0_,
user0_.staffId as staffId3_0_,
user0_.username as username4_0_ 
from
dbo.InvAllUser user0_ 
where
user0_.staffId=?
2020-05-14 10:36:38.278 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [TEST123]
2020-05-14 10:36:38.808 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [INTEGER]) - [1]
2020-05-14 10:36:38.811 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([role2_0_] : [VARCHAR]) - [admin]
2020-05-14 10:36:38.812 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([staffId3_0_] : [VARCHAR]) - [TEST123]
2020-05-14 10:36:38.812 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([username4_0_] : [VARCHAR]) - [lightlce]
2020-05-14 10:36:38.837 DEBUG 50878 --- [nio-8080-exec-6] org.hibernate.SQL                        : 
select
applicatio0_.id as id1_1_0_,
applicatio0_.applicationName as applicat2_1_0_,
applicatio0_.ownerId as ownerId3_1_0_ 
from
dbo.InvApplication applicatio0_ 
where
applicatio0_.id=?
Hibernate: 
select
applicatio0_.id as id1_1_0_,
applicatio0_.applicationName as applicat2_1_0_,
applicatio0_.ownerId as ownerId3_1_0_ 
from
dbo.InvApplication applicatio0_ 
where
applicatio0_.id=?
2020-05-14 10:36:38.839 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [2]
2020-05-14 10:36:39.427 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([applicat2_1_0_] : [VARCHAR]) - [ApplicationDemo]
2020-05-14 10:36:39.427 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([ownerId3_1_0_] : [INTEGER]) - [2]
2020-05-14 10:36:39.546 DEBUG 50878 --- [nio-8080-exec-6] org.hibernate.SQL                        : 
insert 
into
dbo.InvCase
(created_at, modified_at, applicationId, approverId, caseDesc, caseTitle, caseType, status, userId) 
values
(?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: 
insert 
into
dbo.InvCase
(created_at, modified_at, applicationId, approverId, caseDesc, caseTitle, caseType, status, userId) 
values
(?, ?, ?, ?, ?, ?, ?, ?, ?)
2020-05-14 10:36:39.553 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [TIMESTAMP] - [Thu May 14 10:36:39 SGT 2020]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [TIMESTAMP] - [Thu May 14 10:36:39 SGT 2020]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [2]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [INTEGER] - [1]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [VARCHAR] - [ApplicationDemo]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [VARCHAR] - [TEST123]
2020-05-14 10:36:39.555 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [VARCHAR] - [new]
2020-05-14 10:36:39.556 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [VARCHAR] - [Pending]
2020-05-14 10:36:39.557 TRACE 50878 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder      : binding parameter [9] as [INTEGER] - [1]
2020-05-14 10:36:40.987  WARN 50878 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not initialize proxy [com.lightlce.CRUD.Entities.User#2] - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy [com.lightlce.CRUD.Entities.User#2] - no Session (through reference chain: com.lightlce.CRUD.Entities.Case["application"]->com.lightlce.CRUD.Entities.Application["owner"]->com.lightlce.CRUD.Entities.User$HibernateProxy$QRpaILkJ["staffId"])]

你的代码有很多问题,因为我真的不知道如何帮助解决它。 但作为快速修复,请尝试为用户对象创建一个新的实体类。

使用此解决方法解决了它。

由于fooService.save(foo);还使用 ID 更新foo对象,因此我可以简单地return foo.getId()实现我想要的,而无需发送另一个 find 方法。

即案件服务

public Integer updateCase(Case aCase) {
caseRepository.save(aCase);
return aCase.getId();
}

最新更新