无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON
Posted
技术标签:
【中文标题】无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON【英文标题】:Unable to return JSON from Hibernate POJO in Spring Boot REST 【发布时间】:2018-07-07 16:53:41 【问题描述】:我正在尝试使用 Spring Boot 创建一个基本的 REST 服务,该服务返回使用 Hibernate 从数据库创建的 POJO,然后将其转换为 JSON 并返回给 REST 调用。
我可以将常规的非 Hibernate POJO 作为 JSON 返回,但对于 Hibernate 对象,我收到此错误:
Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.example.springboottest.model.Person_$$_jvst48e_0["handler"])
这是我的代码:
Person.java
@Entity
@Table(name = "people")
public class Person implements Serializable
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String nameLast;
private String nameFirst;
@Temporal(TemporalType.DATE)
private Date dob;
protected Person()
public Person(String nameLast, String nameFirst, Date dob)
this.nameLast = nameLast;
this.nameFirst = nameFirst;
this.dob = dob;
// Getters and Setters...
PersonRepository.java
@Repository
public interface PersonRepository extends JpaRepository<Person, Long>
PersonController.java
@RestController
public class PersonController
@Autowired
PersonRepository personRepository;
@GetMapping("/person/id:\\d+")
public Person getPersonByID(@PathVariable long id)
return personRepository.getOne(id);
如果有人可以帮助我理解为什么这不起作用,将不胜感激。谢谢!
【问题讨论】:
空bean的错误信息,你确定给定ID的那个人还是找到了? 您可以从控制器调用 DaoImpl,您可以在其中从 Hibernate 检索列表,然后当您在控制器中获取列表时,您可以使用 GSON 或使用 jackson binder 将其转换为 JSON。跨度> 正确答案:https://***.com/questions/24482117/when-use-getone-and-findone-methods-spring-data-jpa 【参考方案1】:原来这都是我用错方法造成的。如果我将return personRepository.getOne(id)
替换为return personRepository.findOne(id)
,则效果很好。我不明白为什么getOne()
不起作用,但这确实解决了问题。
【讨论】:
【参考方案2】:字段的 getter 必须是 public
。
如果这不起作用。您可能必须使用诸如 PersonDto.java 之类的 POJO,它只有这三个字段,以及这三个字段的 getter 和 setter。
【讨论】:
【参考方案3】:这可能不是原因,但这是推荐的做法。而不是
@Autowired
PersonRepository personRepository;
这样做
PersonRepository personRepository;
@Autowired
public PersonController(PersonRepository personRepository)
this.personRepository = personRepository;
另外,在新的 Spring 启动中,我认为您不必实现 Serializable
。如果我是正确的,它会在您使用 @Entity
注释时自动为您配置。
另外,尝试使空的Person()
构造函数public
。
【讨论】:
【参考方案4】:我也遇到了这个错误并得到了解决,并继续使用 getOne()。当我将实体作为直接响应发送时,这导致了错误。有两种方法可以解决这个问题:
-
使用
public ResponseEntity<UserEntity> getOneUser(@PathVariable Integer userid)
return new ResponseEntity<>(userServiceImplementation.getOneUser(userid), HttpStatus.OK)
或者将Entity转换成DTOModelMapper mapper = new ModelMapper();
mapper.map(entityObject,DTOCLass.class);
然后返回。
因为这篇文章很旧,所以更新它,这样像我这样的人就不会卡住了。
【讨论】:
【参考方案5】:如果之前在同一事务中获取了实体,则在 findByName() 中会发生同样的事情(获取代理而不是真实对象)。对于 getOne() 它由 Spring 记录,但对于 findByName() 它却出人意料地发生。解决方法是使用 Hibernate.unproxy()。
var optionalPotus= potusRepository.findByName("Biden");
if(optionalPotus.isEmpty())
return optionalPotus;
Potus potus= optionalPotus.get();
if(!(potus instanceof HibernateProxy))
return optionalPotus;
// This branch should never occur, but it happens sometimes.
return Optional.of((Potus)Hibernate.unproxy(optionalPotus.get()));
【讨论】:
【参考方案6】:在 Spring Data JPA 中默认 T getOne(ID id) 和 可选的 findById(ID id) 方法将 延迟加载对象 在这里在加载数据之前 jackson api 尝试将其转换为 json。
这意味着杰克逊正在尝试将一个空对象转换为 json,这是我们遇到的错误。
我不确定 T getOne(ID id) 因为它在 spring data jpa 2.5.2 中已被弃用,但如果您将覆盖 Optional findById(ID id) 的声明 在您的存储库界面中,它将解决您的问题。
请看下面的代码sn-p:
@Repository
公共接口 BookRepository 扩展 JpaRepository
public Optional<Book> findById(Integer id);
【讨论】:
以上是关于无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON的主要内容,如果未能解决你的问题,请参考以下文章
无法从同一网络中的另一台计算机访问在我的计算机中运行的 SPRING BOOT 应用程序的 REST API
Spring boot:无法从另一个 Origin 访问安全资源 - CORS - Spring Security - Spring data rest
Rest Controller无法识别Spring Boot App中的GET请求
无法使用 Spring Boot 自动配置访问 REST 控制器