0

我正在尝试使用多对多关联和弹簧将现有工作人员与现有任务相关联,但是当我使用 PUT/PATCH 路由时,无法使用 GET / 从(仅)这些项目中获取任何数据任务/{taskId} 或 GET /dev/{devId}。

这是两个模型。工人模型:

@Entity
@Table(name = "Workers")
public class Worker implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String workerName;
    private String passwd;

    @RestResource(path = "/assocTask")
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinTable(name = "tasks_workers",
            joinColumns = @JoinColumn(name = "worker_id",  referencedColumnName = "id",nullable = false, updatable = false),
            inverseJoinColumns = @JoinColumn(name = "task_id", referencedColumnName = "id", nullable = false, updatable = false))
    //@JsonManagedReference
    private List<Task> tasks = new ArrayList<>();

    public Worker() {
    }

    public Worker(String name, String password) {
        this.workerName = name;
        this.passwd = password;
    }

    public String getName() {
        return workerName;
    }

    public void setName(String name) {
        this.workerName = name;
    }

    public String getPassword() {
        return passwd;
    }

    public void setPassword(String password) {
        this.passwd = password;
    }

    public List<Task> getTasks() {
        return tasks;
    }

    public void setTasks(List<Task> tasks) {
        this.tasks = tasks;
    }

    public Long getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "id=" + id +
                ", workerName='" + workerName + '\'' +
                ", passwd='" + passwd + '\'' +
                ", tasks=" + tasks +
                '}';
    }
}

和任务模型:

@Entity
@Table(name = "Tasks")
public class Task implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String description;

    @ManyToMany(mappedBy = "tasks", fetch = FetchType.LAZY)
    @JsonBackReference
    private List<Worker> workers = new ArrayList<>();

    public Task() {
    }

    public Task(@NotNull String title, @NotNull String description) {
        this.title = title;
        this.description = description;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


    public List<Worker> getWorkers() {
        return workers;
    }

    public void setWorkers(List<Worker> workers) {
        this.workers = workers;
    }

    @Override
    public String toString() {
        return "Task{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", description='" + description + '\'' +
                ", workers=" + workers +
                '}';
    }
}

如果我 GET /tasks/1,这是我得到的错误,例如:

Method threw 'java.lang.StackOverflowError' exception. Cannot evaluate java.util.Optional.toString()

来自服务实现以从数据库中获取它:

    @Override
public Task getTaskById(Long taskId) throws TaskNotFoundException {
    if (taskId == null || taskId < 0) {
        LOGGER.error("Invalid params received");
        throw new Error("INVALID_ID");
    }

    return taskRepository.findById(taskId)
            .orElseThrow(() -> new TaskNotFoundException(taskId, messageSource));
}

这是hibernate执行的查询:

select
    tasks0_.worker_id as worker_id1_2_0_,
    tasks0_.task_id as task_id2_2_0_,
    task1_.id as id1_1_1_,
    task1_.description as descript2_1_1_,
    task1_.title as title5_1_1_ 
from
    tasks_workers tasks0_ 
inner join
    tasks task1_ 
        on tasks0_.task_id=task1_.id 
where
    tasks0_.worker_id=?

如果我在 Postgres 中运行它,我会得到预期的结果......似乎它在无限循环......但是导致溢出的原因是什么,为什么它不会在关联之前或破坏它之后发生?

有任何想法吗?

4

1 回答 1

-1

StackOverflowError方法中发生的信息是否不足以toString让您找出问题?假设您调用Worker.toString()id 为 1 的工作人员。在Worker.toString()您调用which for each callList.toString()时。然后在你调用which 是你输入无限递归的地方,因为每个连接到的都是列表的一部分,反之亦然,每个连接到的都是列表的一部分。这是一个循环对象图。tasksTaskTask.toString()Task.toString()List.toString()workersTaskWorkertasksWorkerTaskworkers

简单的解决方案,只是不要调用toString()可能具有反向引用的集合。或者决定谁是“所有者”,只打电话toString给拥有者。

于 2020-12-22T08:55:13.820 回答