Spring 一对多关系抛出异常:org.springframework.http.converter.HttpMessageNotWritableException
Posted
技术标签:
【中文标题】Spring 一对多关系抛出异常:org.springframework.http.converter.HttpMessageNotWritableException【英文标题】:Spring One-To-Many relationship throws Exception : org.springframework.http.converter.HttpMessageNotWritableException 【发布时间】:2020-04-28 20:40:50 【问题描述】:我尝试使用 spring 在两个实体之间创建简单的关系。有一个 User
实体包含许多 profile
实体。
用户实体
@Entity
public class User
@OneToMany(mappedBy = "user")
private List<Profile> profiles;
public List<Profile> getProfiles()
return profiles;
public void setProfiles(List<Profile> profiles)
this.profiles = profiles;
个人资料实体
@Entity
public class Profile
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
public User getUser()
return user;
public void setUser(User user)
this.user = user;
当我尝试在 @RestController
中查找带有 this.profileRepository.findById(id).get()
的个人资料时,我收到此错误:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: User.profiles, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: User.profiles, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->User["profiles"])]
The server encountered an unexpected condition that prevented it from fulfilling the request.
谁能向我解释为什么这不起作用?我跟着this教程。
【问题讨论】:
交易已关闭。如果知道需要相关对象,则应该急切地而不是懒惰地获取关系。 本教程中没有“其余控制器”(除了存储库...具有“内置”控制器),您可能只是缺少控制器类/方法上的@Transactional
注释(like here) ...advanced issue here
【参考方案1】:
我遇到了同样的问题。 但我收到“已解决 [org.springframework.http.converter.HttpMessageNotWritableException:无法写入 JSON:无法延迟初始化角色集合:”的错误消息: 因为我没有在 viewDTO 中声明 toString 方法
以下是我做过的事情
-
在服务方法中声明了@Transactional。
在持久性 DTO 中声明该字段如下
@Convert(converter = StringListConverter.class)
@JsonIgnore
@ElementCollection
protected List<String> someField;
在哪里
public class StringListConverter implements AttributeConverter<List<String>, String>
@Override
public String convertToDatabaseColumn(List<String> list)
return String.join(",", list);
@Override
public List<String> convertToEntityAttribute(String joined)
return new ArrayList<>(Arrays.asList(joined.split(",")));
-
正在根据持久性 DTO 创建 viewDTO 并在响应实体中设置 viewDTO。
【讨论】:
【参考方案2】:正如Mandar所说,你可以通过eager fetch
解决它。但是,如果您不想获取所有我的意思是eager fetch
,那么您必须将它们初始化为像这样的相关类的延迟获取,您的 Profile 类:
@JsonIgnoreProperties("hibernateLazyInitializer", "handler")
@Entity
public class Profile implements Serializable
//
//
.. your other stuffs
编辑:也像这样改变你的用户实体:
@Entity
public class User implements Serializable
@OneToMany(mappedBy = "user")
private List<Profile> profiles = new LinkedHashSet<Profile>();
//...other stufs..
.
.
希望,这会有所帮助!
【讨论】:
顺便说一句:我通常建议将业务实体与持久性实体以及 DTO 分开。所以实际上,这一类应该是三个类:一个用于(外部)表示的 DTO、一个业务实体和一个持久性实体。 感谢您回答我的问题。正如您所描述的,我已将@JsonIgnoreProperties
添加到配置文件实体中。但这仍然是同样的问题。你能再解释一下吗?
@Turing85 你能解释一下业务实体的含义吗?
你添加了这整件事@JsonIgnoreProperties("hibernateLazyInitializer", "handler")
吗?好的,这会在其反序列化过程中为延迟获取的数据进行初始化,因为这些数据在您第一次调用该对象时并未获取。另外,请检查我的编辑
是的,我已经添加了整个注释以上是关于Spring 一对多关系抛出异常:org.springframework.http.converter.HttpMessageNotWritableException的主要内容,如果未能解决你的问题,请参考以下文章
使用 Hibernate 删除一对多关系中的对象时 PostgreSQL 异常
Spring boot 无法评估表达式方法抛出 'org.hibernate.LazyInitializationException' 异常。使用 getter,ManyToMany 关系