Spring 使用 Retrofit2 POST 时启动服务器错误,仅当数据库中存在关系时才会发生
Spring Boot server error while POST with Retrofit2, only happens when there are relationships in the database
我 POST 一些 Retrofit2 的数据到 Spring 启动 REST 服务,服务器中发生了很多异常。当我的数据库中有关系时会发生这种情况。
我在 Heroku 服务上运行的 Spring 引导应用程序上有一个 REST 服务,我正在使用 Android 应用程序执行登录和注册任务,我在 Android 到 POST 数据到 REST 服务,一切正常,直到出于某些其他原因我在我的数据库中创建用户之间的关系,这个关系是 "follow",这是,创建follow
table 中的关系,其中我有正在关注的用户的 ID
和被关注的用户的 ID
。当我在数据库中创建这种关系并尝试使用我创建的方法登录时,我在 REST 服务中遇到了一堆错误,我不知道为什么会这样。
所以在 Android 中,我调用了我的 Retrofit2 客户端和一个创建服务的方法,该方法将 UserService.class
作为参数传递给 HTTP 方法。我还将 class User
的用户作为参数传递,其中包含我想要 POST 的信息,然后我调用入队方法。
RetrofitClient.createService(UserService.class).login(user).enqueue(new CallBack<User>(){
@Override
public void onResponse(Call<User> call, Response<User> response) {
//Some logic here
}
});
进入我的UserService.java
我有POST用户对象信息的方法
public interface UserService {
@POST("login")
public Call<User> login(@Body User user);
}
现在在后端,我有一个 REST 控制器,其中有将用于 Retrofit2 的登录端点。
@PostMapping(path = "login", consumes = "application/json", produces = "application/json")
@CrossOrigin(origins = "*", methods= {RequestMethod.GET,RequestMethod.POST})
public Object login(@RequestBody String json) {
//Some logic here
}
正如我所说,当用户与数据库之间没有任何关系时,此端点运行良好,但是当用户关注另一个用户时,即当关注中有新行时 table,让我们说:
关注 table:
id_follow id_user_follower id_user_following
1 1 2
在上面的示例中,用户 1 关注用户 2,当我尝试登录时,使用 UserService
class 中的登录方法会抛出一堆错误.
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
这重复了 300 多行错误。
这里的问题是,在服务器 return 一个 200 HTTP 响应的一堆错误之间,我在 Spring 引导中管理了异常,我捕获了它,当我捕获时,我发送了一个代码我的 Android Retrofit2 客户端出现错误,但无法登录。
预期结果:
将 POST 从 Retrofit2 发送到 Spring 后,响应必须是 HTTP 200 响应,但服务器中不会发生异常。
实际结果:
服务器有一个 200 HTTP 响应,但服务器有很多异常,return Android 应用程序的错误代码和登录不起作用。
这是我想要从 Spring Boot 中的 RestController return 作为 JSON 的实体。
@Entity
@Table(name = "users")
public class User extends AuditModel{
private static final long serialVersionUID = 1700575815607801150L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idUser;
private String name;
private String lastName;
@Column(name = "nick_name", unique = true)
private String nickName;
private String avatarResource;
@Column(unique=true)
private String email;
private String password;
private String birthDate;
private String gender;
private String postalCode;
private int active;
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAvatarResource() {
return avatarResource;
}
public void setAvatarResource(String avatarResource) {
this.avatarResource = avatarResource;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getId() {
return idUser;
}
public void setId(Long idUser) {
this.idUser = idUser;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
/* Relations */
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Comment> comments;
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserMemory> userMemories;
public List<UserMemory> getUserMemories() {
return userMemories;
}
public void setUserMemories(List<UserMemory> userMemories) {
this.userMemories = userMemories;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Vote> votes;
public List<Vote> getVotes() {
return votes;
}
public void setVotes(List<Vote> votes) {
this.votes = votes;
}
@OneToMany(mappedBy = "userFollower", fetch = FetchType.LAZY)
private List<Follow> usersFollowers;
public List<Follow> getUsersFollowers() {
return usersFollowers;
}
public void setUsersFollowers(List<Follow> usersFollowers) {
this.usersFollowers = usersFollowers;
}
@OneToMany(mappedBy = "userFollowing", fetch = FetchType.LAZY)
private List<Follow> usersFollowing;
public List<Follow> getUsersFollowing() {
return usersFollowing;
}
public void setUsersFollowing(List<Follow> usersFollowing) {
this.usersFollowing = usersFollowing;
}
}
所以,问题是我在后端使用 ObjectMapper
class 的 writeValueAsString
像这样。
public Object register(@RequestBody String json){
User user = new User();
user.set...
...
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(user);
}
出于某种原因,当与数据库建立关系时,writeValueAsString
方法会针对递归行为给出 WhosebugException,这是与 JPA 或 Hibernate 相关的问题,我不确定是哪一个.
解决方案是编写我自己的方法来使用我的 POJO 的信息构建一个 JSON对象:
public String buildUserJSON(User user) {
JSONObject userJson = new JSONObject();
userJson.put("idUser", user.getIdUser());
...
return userJson.toString();
}
然后在我的RestController
中调用这个方法来构建我想要return的JSON。正如我所说,我不知道问题出在哪里,但至少这是我的解决方案。
注意:我找到了解决这个问题的方法,因为在过去我遇到过类似的问题,但是当我尝试 return a List<T>
作为 JSON,所以,我认为这与同一件事有关。
此致。
通过 fetchtype.LAZY
,某些值在序列化期间将不存在。这将使 ObjectMapper
尝试获取这些,这一切都将以某种无限循环结束。
不建议序列化 @Entity
注释 类,因为数据库表可能会更改,而这反过来会更改调用客户端的 API。
最好的方法是在序列化之前将数据传输到特定的 ResponseDTO
,这样 API 和数据库表可以在不破坏任何内容的情况下进行更改。
问题出在 Jackson 身上,所以要解决这个问题,您最常在实体关系中使用两个注释。
更多信息,请看下link:Here is the answer
希望对大家有所帮助。
我 POST 一些 Retrofit2 的数据到 Spring 启动 REST 服务,服务器中发生了很多异常。当我的数据库中有关系时会发生这种情况。
我在 Heroku 服务上运行的 Spring 引导应用程序上有一个 REST 服务,我正在使用 Android 应用程序执行登录和注册任务,我在 Android 到 POST 数据到 REST 服务,一切正常,直到出于某些其他原因我在我的数据库中创建用户之间的关系,这个关系是 "follow",这是,创建follow
table 中的关系,其中我有正在关注的用户的 ID
和被关注的用户的 ID
。当我在数据库中创建这种关系并尝试使用我创建的方法登录时,我在 REST 服务中遇到了一堆错误,我不知道为什么会这样。
所以在 Android 中,我调用了我的 Retrofit2 客户端和一个创建服务的方法,该方法将 UserService.class
作为参数传递给 HTTP 方法。我还将 class User
的用户作为参数传递,其中包含我想要 POST 的信息,然后我调用入队方法。
RetrofitClient.createService(UserService.class).login(user).enqueue(new CallBack<User>(){
@Override
public void onResponse(Call<User> call, Response<User> response) {
//Some logic here
}
});
进入我的UserService.java
我有POST用户对象信息的方法
public interface UserService {
@POST("login")
public Call<User> login(@Body User user);
}
现在在后端,我有一个 REST 控制器,其中有将用于 Retrofit2 的登录端点。
@PostMapping(path = "login", consumes = "application/json", produces = "application/json")
@CrossOrigin(origins = "*", methods= {RequestMethod.GET,RequestMethod.POST})
public Object login(@RequestBody String json) {
//Some logic here
}
正如我所说,当用户与数据库之间没有任何关系时,此端点运行良好,但是当用户关注另一个用户时,即当关注中有新行时 table,让我们说:
关注 table:
id_follow id_user_follower id_user_following
1 1 2
在上面的示例中,用户 1 关注用户 2,当我尝试登录时,使用 UserService
class 中的登录方法会抛出一堆错误.
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
这重复了 300 多行错误。
这里的问题是,在服务器 return 一个 200 HTTP 响应的一堆错误之间,我在 Spring 引导中管理了异常,我捕获了它,当我捕获时,我发送了一个代码我的 Android Retrofit2 客户端出现错误,但无法登录。
预期结果:
将 POST 从 Retrofit2 发送到 Spring 后,响应必须是 HTTP 200 响应,但服务器中不会发生异常。
实际结果:
服务器有一个 200 HTTP 响应,但服务器有很多异常,return Android 应用程序的错误代码和登录不起作用。
这是我想要从 Spring Boot 中的 RestController return 作为 JSON 的实体。
@Entity
@Table(name = "users")
public class User extends AuditModel{
private static final long serialVersionUID = 1700575815607801150L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idUser;
private String name;
private String lastName;
@Column(name = "nick_name", unique = true)
private String nickName;
private String avatarResource;
@Column(unique=true)
private String email;
private String password;
private String birthDate;
private String gender;
private String postalCode;
private int active;
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAvatarResource() {
return avatarResource;
}
public void setAvatarResource(String avatarResource) {
this.avatarResource = avatarResource;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getId() {
return idUser;
}
public void setId(Long idUser) {
this.idUser = idUser;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
/* Relations */
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Comment> comments;
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserMemory> userMemories;
public List<UserMemory> getUserMemories() {
return userMemories;
}
public void setUserMemories(List<UserMemory> userMemories) {
this.userMemories = userMemories;
}
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Vote> votes;
public List<Vote> getVotes() {
return votes;
}
public void setVotes(List<Vote> votes) {
this.votes = votes;
}
@OneToMany(mappedBy = "userFollower", fetch = FetchType.LAZY)
private List<Follow> usersFollowers;
public List<Follow> getUsersFollowers() {
return usersFollowers;
}
public void setUsersFollowers(List<Follow> usersFollowers) {
this.usersFollowers = usersFollowers;
}
@OneToMany(mappedBy = "userFollowing", fetch = FetchType.LAZY)
private List<Follow> usersFollowing;
public List<Follow> getUsersFollowing() {
return usersFollowing;
}
public void setUsersFollowing(List<Follow> usersFollowing) {
this.usersFollowing = usersFollowing;
}
}
所以,问题是我在后端使用 ObjectMapper
class 的 writeValueAsString
像这样。
public Object register(@RequestBody String json){
User user = new User();
user.set...
...
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(user);
}
出于某种原因,当与数据库建立关系时,writeValueAsString
方法会针对递归行为给出 WhosebugException,这是与 JPA 或 Hibernate 相关的问题,我不确定是哪一个.
解决方案是编写我自己的方法来使用我的 POJO 的信息构建一个 JSON对象:
public String buildUserJSON(User user) {
JSONObject userJson = new JSONObject();
userJson.put("idUser", user.getIdUser());
...
return userJson.toString();
}
然后在我的RestController
中调用这个方法来构建我想要return的JSON。正如我所说,我不知道问题出在哪里,但至少这是我的解决方案。
注意:我找到了解决这个问题的方法,因为在过去我遇到过类似的问题,但是当我尝试 return a List<T>
作为 JSON,所以,我认为这与同一件事有关。
此致。
通过 fetchtype.LAZY
,某些值在序列化期间将不存在。这将使 ObjectMapper
尝试获取这些,这一切都将以某种无限循环结束。
不建议序列化 @Entity
注释 类,因为数据库表可能会更改,而这反过来会更改调用客户端的 API。
最好的方法是在序列化之前将数据传输到特定的 ResponseDTO
,这样 API 和数据库表可以在不破坏任何内容的情况下进行更改。
问题出在 Jackson 身上,所以要解决这个问题,您最常在实体关系中使用两个注释。
更多信息,请看下link:Here is the answer
希望对大家有所帮助。