为什么我不能在通过put/patch路由关联后获得一个或两个spring“多对多”实体的信息?

kuarbcqp  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(250)

这个问题在这里已经有答案了

保存对象的tostring值时发生stackoverflow错误-java/hibernate/spring(2个答案)
18天前关门了。
我正在尝试使用多对多关联和spring将现有的worker与现有的任务关联起来,但是当我使用put/patch路由时,无法使用get/tasks/{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 +
                '}';
    }
}

这是我在获取/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中运行它,我会得到预期的结果。。。好像它在无限循环。。。但是,是什么导致了溢出,为什么它不发生在协会之前或之后打破它?
有什么想法吗?

vdzxcuhz

vdzxcuhz1#

是一个 StackOverflowError 有了发生在 toString 方法对你来说不够明显,不足以解决问题?假设你打电话来 Worker.toString() 在id为1的工作进程上。在 Worker.toString() 你打电话来 List.toString()tasks 每一个 Task 电话 Task.toString() . 在 Task.toString() 你再打给我 List.toString()workers 这就是你进入无限递归的地方,因为 Task 连接到 Worker 是这个计划的一部分 tasks 列表和其他方式,每 Worker 连接到 Task 是这个计划的一部分 workers 列表。这是一个循环对象图。
简单的解决办法,就是不要打电话 toString() 在可能有反向引用的集合上。或者决定谁是“主人”并且只打电话 toString 在拥有方。

相关问题