hibernate - 如何在 Spring Data JPA 中合并子实体

标签 hibernate jpa spring-data-jpa hibernate-mapping

我将 Spring Data 与 CrudRepository 结合使用.我正在尝试将 Parent with Cascade 保存到子实体,并且我正在为 Hibernate 提供合并子实体的可能性,但我收到错误 a different object with the same identifier value was already associated with the session .当他坚持两个具有其他子实体(RecipeIngredients)的父实体时,可能会发生这种情况。我正在尝试覆盖 equals 和 hashcode 以仅关注 idname ,但它没有任何改变。 Recipe对象相同但 List<RecipeIgredients>是不同的。关于如何解决它的任何想法?

例子:

这是我存在的对象:

{
  "id": 100,
  "name": "salat",
  "ingredients": [
    {
      "ingredient": {
        "id": 100,
        "name": "banana"
      },
      "count": 2
    },
    {
      "ingredient": {
        "id": 1,
        "name": "eggs"
      },
      "count": 1
    }
  ]
}

我想将其更新为以下(删除一种成分):

{
  "id": 100,
  "name": "salat",
  "ingredients": [
    {
      "ingredient": {
        "id": 100,
        "name": "bannana"
      },
      "count": 2
    }
  ]
}

父级:

@Entity
@Data
public class Recipe {

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "recipe_generator")
@SequenceGenerator(name="recipe_generator", sequenceName = "recipe_seq")
@Column(name = "id", nullable = false)
private Long id;

@NaturalId
@Column
private String name;

@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true)
private List<RecipeIngredients> ingredients;

}

child 在中 table

@Entity
@Data
public class RecipeIngredients implements Serializable {

@EmbeddedId
private RecipeIngredientsId recipeIngredientsId;

@ManyToOne(fetch = FetchType.LAZY)
@MapsId("recipeId")
private Recipe recipe;

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@MapsId("ingredientId")
private Ingredient ingredient;

@Column
private Integer count;

public RecipeIngredients(Recipe recipe, Ingredient ingredient) {
    this.recipe = recipe;
    this.ingredient = ingredient;
    this.recipeIngredientsId = new RecipeIngredientsId(recipe.getId(), ingredient.getId());
}

child

@Entity
@Data
public class Ingredient {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ingredient_generator")
    @SequenceGenerator(name="ingredient_generator", sequenceName = "ingredient_seq")
    @Column(name = "id", updatable = false, nullable = true)
    private Long id;

    @NaturalId
    @Column(unique = true)
    private String name;

}

最佳答案

我可以举一个我的项目的例子,希望它能有所帮助:

父级:

package com.yoav.todolist.models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "accounts")
public class Account {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @OneToMany(
            mappedBy = "account",
            orphanRemoval = true,
            cascade = CascadeType.ALL
    )
    private List<Task> tasks = new ArrayList<>();

    public Account(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public Account() {
    }

    public void removeTask(Task task) {
        tasks.remove(task);
        task.setAccount(null);
    }

    public void addTask(Task task) {
        tasks.add(task);
        task.setAccount(this);
    }

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

    public void setTasks(List<Task> tasks) {
        this.tasks.forEach(i -> i.setAccount(null));
        this.tasks.clear();

        tasks.forEach(i -> {
            i.setAccount(this);
            addTask(i);
        });
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

    @Override
    public boolean equals(Object account) {
        return ((Account)account).getUsername().equals(this.username);
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

child :

package com.yoav.todolist.models;

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "tasks")
public class Task {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;

    @Column(name = "task")
    private String task;

    @ManyToOne(fetch = FetchType.LAZY)
    @JsonIgnore
    private Account account;

    @Temporal(TemporalType.DATE)
    @Column(name = "date_of_creation_task")
    private Date date;

    public Task(String task) {
        this.date = new Date();
        this.task = task;
    }

    public Task() {
        this.date = new Date();
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTask() {
        return task;
    }

    public void setTask(String task) {
        this.task = task;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public boolean equals(Object task) {
        return ((Task)task).getId() == this.id;
    }

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

    @Override
    public int hashCode() {
        return 31;
    }

}

在我的例子中,我只需要获取实体,例如 accountSerice.getById(1); 然后在我的例子中,我只需要执行 account.setTasks(tasks);//任务只是 child 的列表@see 帐户(父)实体中的 setTasks()

关于hibernate - 如何在 Spring Data JPA 中合并子实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61606944/

相关文章:

java - Hibernate复合键映射问题

java - Hibernate:java.sql.SQLIntegrityConstraintViolationException:无法添加或更新子行:外键约束失败

hibernate - 了解乐观锁定 StaleObjectStateException

java - 在 Hibernate Component 标签中延迟加载不起作用

java - genericDAO 的结构

java - 构造函数中的 Spring Data JPA JPQL 列表

mysql - Hibernate 创建冗余的多对多表

Spring Boot 。如何禁用 JPA Conditionaliy 的初始化

java - HIbernate Maven项目:没有名为EntityManager的持久性提供程序

java - Hibernate OneToMany 映射