java - Spring Boot 服务器在使用 Retrofit2 进行 POST 时出错,仅当数据库中存在关系时才会发生

标签 java android rest spring-boot retrofit2

我使用 Retrofit2 将一些数据发布到 Spring Boot REST 服务,服务器中发生了很多异常。当我的数据库中有关系时就会发生这种情况。

我在 Spring Boot 应用程序上有一个 REST 服务,该应用程序在 Heroku 服务上运行,我正在使用 Android 应用程序执行登录和注册任务,我在 Android 中使用 Retrofit2 将数据 POST 到 REST 服务,一切一直运行良好,直到由于其他原因我在数据库中的用户之间创建了一个关系,这个关系是一个“follow”,也就是说,在 follow 表中创建一个关系,其中我有 关注的用户的 ID 和关注的用户的 ID。当我在数据库中创建此关系并尝试使用我创建的方法登录时,我在 REST 服务中遇到了一堆错误,我不知道为什么会发生这种情况。

因此,在 Android 中,我调用了 Retrofit2 客户端以及创建服务的方法,该方法使用 HTTP 方法将 UserService.class 作为参数传递。我还将 User 类的用户作为参数传递,其中包含我想要 POST 的信息,然后调用 enqueue 方法。

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 Controller ,其中有将用于 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
}

正如我所说,当用户与数据库之间没有关系时,此端点运行良好,但是当用户关注另一个用户时,即当后续表中出现新行时,可以说:

如下表:

id_follow id_user_follower id_user_following
1         1                 2

在上面的示例中,用户 1 关注用户 2,当我尝试登录时,即使用 UserService 类中的登录方法,它会抛出一堆错误。

    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 多行错误。

这里的问题是,在一堆错误之间,服务器返回 200 HTTP 响应,我在 Spring Boot 中管理了异常,并且捕获了该异常,当捕获时,我将错误代码发送到我的 Android Retrofit2 客户端,但是无法登录。

预期结果:

将 POST 从 Retrofit2 发送到 Spring Boot 后,响应必须是 HTTP 200 响应,但服务器中不得发生异常。

实际结果:

服务器有一个 200 HTTP 响应,但服务器中有很多异常,它们向 Android 应用程序返回错误代码,并且登录不起作用。

这是我想要从 Spring Boot 中的 RestController 以 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;
    }
}

最佳答案

通过使用fetchtype.LAZY,某些值在序列化过程中将不存在。这将使 ObjectMapper 尝试获取这些内容,而这一切最终都会陷入某种无限循环。

永远不建议序列化 @Entity 带注释的类,因为数据库表可能会更改,进而会更改调用客户端的 API。

最好的方法是在序列化之前将数据传输到特定的 ResponseDTO,以便 API 和数据库表可以在不破坏任何内容的情况下进行更改。

关于java - Spring Boot 服务器在使用 Retrofit2 进行 POST 时出错,仅当数据库中存在关系时才会发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57243912/

相关文章:

安卓, ImageView 拉伸(stretch)

java - 单击其他按钮后如何启用/禁用按钮?

java - 在测试上下文中传递 HTTP 调用

java - 使用 Jersey 加密 RESTful 服务的数据

java - Objectify - 如何按 boolean 值过滤?

java - s3fs无法挂载存储桶

Java程序不是调用方法

java - 在java中读取下一个单词

java - 删除空文件夹算法

asp.net - 在 Azure 上创建 ASP.NET MVC RESTful API 的指南