Как вставить несколько записей с репозиториями JPA в таблицу с составным PK, и одна из них автоматически увеличивается? - PullRequest
0 голосов
/ 20 сентября 2019

Я создаю контроллер с пружинной загрузкой для хранения списка записей, но таблица, в которой будут храниться записи, имеет составной PK (два поля), и одно из полей композиции - auto_incrementable, мои объектыопределяется следующим образом:

TaskPK.java

@Embeddable
public class TaskPK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(name="taskflow_template_task_id", unique=true, nullable=false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer taskflowTemplateTaskId;

    @Column(name="taskflow_template_id", insertable=false, updatable=false, unique=true, nullable=false)
    private Integer taskflowTemplateId;

// Getters, setters and constructors
}

На этом ПК taskflowTemplateTaskId представляет собой поле AI

Task.java

public class Task extends BaseEntity implements Serializable, Persistable<TaskPK> {
    private static final long serialVersionUID = 1L;

    @EmbeddedId
    private TaskPK id = new TaskPK();

    @Column(name="task_id")
    private Integer taskId;

    @Column(name="display_order", nullable=false)
    private int displayOrder;

    //bi-directional many-to-one association to TaskflowTemplate
    @ManyToOne
    @JoinColumn(name="taskflow_template_id", nullable=false, insertable=false, updatable=false)
    private TaskflowTemplate taskflowTemplate;

    @Override
    public boolean isNew() {
        return (id.getTaskflowTemplateTaskId() == null || id.getTaskflowTemplateId() == null);
    }

У объекта задачи есть репозитории JPA с данными о пружине, связанные без каких-либо пользовательских запросов

Наконец, это код, который я использую для хранения данных, это простая функциявызывается из контроллера

@Transactional
public void createTask(List<Task> tasks){
    taskRepository.saveAll(tasks)
}

И данные, которые я получаю, представлены в следующем JSON:

[
  {
    "displayOrder": 1,
    "taskId": 1,
    "id": {
        "taskflowTemplateId" : "1"
     }
  },
  {
    "displayOrder": 2,
    "taskId": 2,
    "id": {
        "taskflowTemplateId" : "1"
     }
  },
  {
    "displayOrder": 3,
    "taskId": 3,
    "id": {
        "taskflowTemplateId" : "1"
     }
  }
]

Когда я запускаю этот код, я получаю это исключение

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.test.taskmaster.entity.Task#TaskPK(taskflowTemplateTaskId=null, taskflowTemplateId=1)]

Итак, я предполагаю, что поле taskflowTemplateTaskId не создается hibernate, вместо этого оно отправляется как null.Когда создается только одна запись, это работает хорошо, потому что в базе данных поле AI заменяется на ноль, но когда я пытаюсь вставить список записей с нулевым taskflowTemplateTaskId, потому что я хочу, чтобы это было сгенерировано, эта ошибка происходит.

Я пытался использовать save внутри цикла и saveAndFlush безуспешно, также я пробовал другой тип GenerationType и даже использовал @Generated (GenerationTime).

1 Ответ

0 голосов
/ 20 сентября 2019

Это означает, что вы пытаетесь сохранить несколько строк в таблице со ссылкой на один и тот же объект.

@Column(name="taskflow_template_task_id", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer taskflowTemplateTaskId;

до

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="taskflow_template_task_id", unique = true, nullable = false)
private Integer taskflowTemplateTaskId;
...