【问题标题】:Assigning id of old object to new object will insert it as duplicate @ManyToMany将旧对象的 id 分配给新对象会将其插入为重复的 @ManyToMany
【发布时间】:2017-11-25 22:08:59
【问题描述】:

我的班级中有一个单向的@ManyToMany 关系,如下所示:

@ManyToMany(cascade = {
        CascadeType.MERGE,
        CascadeType.PERSIST
})
@JoinTable(
        name=TABLE_NAME_JOB_JOB_TYPE,
        joinColumns=@JoinColumn(name=COLUMN_JOB_ID, referencedColumnName = COLUMN_JOB_ID),
        inverseJoinColumns = @JoinColumn(name=COLUMN_JOB_TYPE_ID, referencedColumnName = COLUMN_JOB_TYPE_ID)
)
@Fetch(FetchMode.JOIN)
private Set<JobTypeModel> types;

由于一个简单的错误,我很难更新 Job Types 的数量,但我终于找到了。 但是,我不知道为什么会发生这种情况。

基本上,我所做的是,我有一个合并旧作业和新作业的方法,而不是从 newJob 中获取所有内容并添加到 oldJob,而是获取 oldJob 的 ID,并将其分配给 newJob。

所以,像这样:

public JobModel mergeAndUpdate(JobModel oldJob, JobModel newJob) {
    getLoggerService().debug(this.getClass().getSimpleName(), "mergeAndUpdate({oldJob}, {newJob})");
    //newJob.setId(oldJob.getId()); //If doing this, then it fails
    //Was trying to avoid doing this:
    oldJob.setX(newJob.getX());
    oldJob.setY(newJob.getY());
    oldJob.setZ(newJob.getZ());

    return getJobRepository().saveAndFlush(oldJob);
    //return getJobRepository().saveAndFlush(newJob);
}

我的 JobRepository 是一个扩展 org.springframework.data.jpa.repository.JpaRepository 的接口

这样做时,当尝试持久化更新(添加一个或删除一个 jobType)时,它会失败。

添加新的jobType时,它会告诉我关联表JOB_JOB_TYPE中有重复条目。

Hibernate: insert into job_job_type (job_id, job_type_id) values (?, ?)
2017-11-26 00:02:28.202  WARN 74560 --- [p-nio-80-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1062, SQLState: 23000
2017-11-26 00:02:28.202 ERROR 74560 --- [p-nio-80-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : Duplicate entry '187-2' for key 'PRIMARY'
2017-11-26 00:02:28.203  INFO 74560 --- [p-nio-80-exec-6] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements

当从 Job 集中删除一个 jobType 并持久化新 Job 时,什么都不会发生 -> 关系仍然存在。

有人知道为什么吗?

注意: 这样做,对于没有@ManyToMany 关系的对象(又名。将旧对象的 ID 添加到新对象,而不是将新对象中的所有其他内容添加到旧对象,将在调用saveAndFlush 方法。

我正在使用: MariaDB 10.1.28 Spring Boot 1.5.4(带有关联的 Spring Boot 启动器数据 jpa)

【问题讨论】:

  • 行为持久化对我来说是合乎逻辑的,你必须先删除旧记录(带有 X id),然后添加具有相同 id 的新记录。也许尝试保存到字段Integer temp id 值,删除旧记录,然后尝试使用来自temp 的id 添加新记录
  • 这意味着两个查询。我解决问题的方法只使用一个查询。我只想知道为什么相反的方法不起作用,以及对实际发生的情况的解释。而且由于我无处可寻,这个特定的问题,我认为在这种情况下它也可能对其他人有所帮助。

标签: java hibernate jpa spring-boot spring-data-jpa


【解决方案1】:

底线是数据库负责。让它为您创建所有 ID。不要尝试在对象上设置 ID。如果您要插入一条新记录,您可以使用空 ID 插入,DB 将分配 ID,当然在插入之后您才知道 ID。但重要的是,如果您在其上(在 POJO 对象上)保留具有 HAS 和 ID 的记录,那么您需要确保它正在执行“更新”操作而不是“插入”,否则您会遇到这个问题。

【讨论】:

  • 当调用 'saveAndFlush' 时,它会进行更新。因此,如果我设置了一个 ID,它将进行更新。如果我从数据库中获取记录,将其映射到一个对象,该对象还将包含一个 ID。如果我更改了上述对象上的其他内容,并保持 ID 不变,那么它正在正确地进行更新。但是这里,我们讲的是@ManyToMany关系,并且更新发生在父表中,而不会发生在关联表中。
  • 查找“级联”。如果没有明显的级联方法,您可能必须对两个表进行手动更新。我对@ManyToMany 生疏了,但在stackoverflow.com/questions/946938/… 之前已经完成了,并在谷歌上搜索了这个“用spring @manytomany 更新”:P 该搜索会得到很多点击。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 2019-12-06
  • 2018-04-12
  • 1970-01-01
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多