Spring Data JPA数据重复

huangapple 未分类评论50阅读模式
英文:

Spring Data JPA data duplication

问题

以下是翻译好的部分:

我有以下的项目结构:

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
    private List<TaskCard> taskCards;
}

public class TaskCard {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "taskCard", fetch = FetchType.LAZY)
    private List<Task> tasks;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;
}

public class Task {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "task_card_id")
    private TaskCard taskCard;
}

问题出在这里。当访问POST任务控制器方法以创建新任务时,我执行以下操作:

@PostMapping
public Task createTask(@CurrentUser UserPrincipal userPrincipal, @PathVariable("cardId") Long cardId, @RequestBody Task task) {
    User user = userService.findUserById(userPrincipal.getId());
    task.setTaskCard(user.getTaskCards().stream()
                         .filter(card -> card.getId().equals(cardId))
                         .findFirst()
                         .get());
    return taskService.saveTask(task);
}

User Principal 是当前用户。但它仅存储元数据,我从中获取id以在用户数据库中查找。在这里值得注意的是,我在数据库中查找用户,从中获取任务卡并查找所需的卡片。然后,我将此值分配给新任务,以使其属于该卡片。之后,我将其保存在存储库中。但问题是,在此之后,为 User 实例创建了另一个相同的卡片,因此每次我添加任务时,我都会得到任务卡的另一个副本,而这些副本在用户中。问题是我不知道它们是如何出现或者如何保存的。在数据库中,一切都井然有序,数据没有重复,但是为什么在从数据库中提取时,我得到的卡片并不是 'user_id' 等于该用户的卡片,而是包括所有卡片,还有重复的卡片?这甚至听起来是难以理解的。我附上了数据库的截图:

这是用户
Spring Data JPA数据重复

这是任务卡片
Spring Data JPA数据重复

这是任务
Spring Data JPA数据重复

如你所见,在数据库中一切都井然有序,没有重复,但在调试中发生了以下情况:
Spring Data JPA数据重复

我添加了5个任务,最后得到了5个卡片的副本,尽管应该只有一个。正如你所看到的,问题的根源在于“本地”用户实例,它保存了重复的内容。如何解决这个问题?

英文:

I have the following project structure:

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = &quot;user&quot;, fetch = FetchType.EAGER)
    private List&lt;TaskCard&gt; taskCards;
}

public class TaskCard {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = &quot;taskCard&quot;, fetch = FetchType.LAZY)
    private List&lt;Task&gt; tasks;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = &quot;user_id&quot;)
    private User user;
}

public class Task {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;  

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = &quot;task_card_id&quot;)
    private TaskCard taskCard;
}

And the problem consists here in what. When accessing the POST Task Controller method to create a new task I do the following:

@PostMapping
public Task createTask(@CurrentUser UserPrincipal userPrincipal, @PathVariable(&quot;cardId&quot;) Long cardId, @RequestBody Task task) {
    User user = userService.findUserById(userPrincipal.getId());
    task.setTaskCard(user.getTaskCards().stream()
                         .filter(card -&gt; card.getId().equals(cardId))
                         .findFirst()
                         .get());
    return taskService.saveTask(task);
}

User Principal is the current user. But it just stores metadata and I take the id from it to find it in the user's database. Here it is worth noting that I am looking for a user in the database and from it I get taskcards and look for the desired card. After that, I assign this value to the new tosk so that it belongs to this card. After that, I save it in the repository. But the problem is that after this, another identical card is created for the User instance, so every time I add a task, I get another copy of the task cards that are in the user. The problem is that I have no idea how they get there or how they are saved. In the database, I have everything in order, the data is not duplicated, but why then when extracting from the database, I do not get the cards that have 'user_id' equal to this user, but everything in a row along with duplicates? It even sounds incomprehensible. I attach screenshots of what my database looks like:

This is users
Spring Data JPA数据重复

This is task cards

Spring Data JPA数据重复

This is tasks

Spring Data JPA数据重复

As you can see in the database everything is in order, there is no duplication, but here's what happens in debug:
Spring Data JPA数据重复

I added 5 tasks and in the end I got 5 duplicates of the card, although it should only be one. As you can see, the whole problem is in the "local" user instance, which stores duplicates. How do I fix this?

答案1

得分: 0

你现在可能正在联合获取集合,当您在模型中使用List时,可能会发生这种情况。我建议您改用Set,即private Set&lt;Task&gt; tasks;

英文:

You are probably join fetching the collections and this is what can happen when you use a List in your model. I suggest you use a Set instead i.e. private Set&lt;Task&gt; tasks;

huangapple
  • 本文由 发表于 2020年5月5日 05:07:35
  • 转载请务必保留本文链接:https://java.coder-hub.com/61601621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定