【问题标题】:Spring-Data JPARepository save method creates a duplicate RecordSpring-Data JPARepository 保存方法创建重复记录
【发布时间】:2020-01-18 18:28:38
【问题描述】:

我正在使用 spring-data 和 hibernate 来创建表和插入数据。从不同的线程中,我发现 JPARepository(来自 CRUDRepository)的保存方法只会在记录已经存在时更新记录。以下是我找到一些信息的线程之一:

https://stackoverflow.com/a/40608937/10356053

我有一个实体正在复制记录(即使对象相同,jpa 也将其视为新插入)。我不确定发生了什么或此问题的解决方案。任何建议表示赞赏。下面是我创建的实体:

CustomerEntity.java:

@Getter
@Setter
@Table(name = "Customers")
@Entity
public class CustomersEntity extends BasicEntity {
      @Id
     @GeneratedValue(generator = "UUID")
     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
     @Column(name = "CustomerId", updatable = false, nullable = false)
     private UUID customerid;

     //and some other fields
}

基本实体.java:

@Getter
@Setter
public class BasicEntity implements serializable {
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at", updatable = false)
    @CreatedDate
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated_at")
    @LastModifiedDate
    private Date updatedAt;
}

Repository.java

@Repository
public interface Repositorty extends JpaRepository<CustomersEntity, UUID> {


}

当我们试图保存上述实体时:

repository.save(customerEntity)

将作为新记录保留在数据库中。任何建议都是有帮助的。我在想这是因为父类的 createdTime 和 updatedTime 吗?如果是,我们如何避免这种情况? TIA。

【问题讨论】:

  • 可能是因为每条记录都有新的 ID UUID customerid; 如果你想更新记录,那么你有相同的 id
  • @Deadpool 如果我的理解是正确的,jpa 会在创建新的 UUID 之前检查是否相等?如果对象相同,它应该只更新记录而不是创建新记录?如果我错了,你能纠正我吗?
  • 我不确定,但你可以尝试使用现有的 id 看看它是否更新@ging
  • @Deadpool 不,它只是在数据库中创建一个新行。
  • 是 createdTime 没有设置的问题吗?因为我在我的机器上尝试了你的代码,并且它为给定的客户 ID 更新了同一行,正如@Deadpool 已经说过的那样。

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


【解决方案1】:

columnDefinition = "BINARY(16)" 添加到 customerid 的 @Column 属性中。

@Getter
@Setter
@Table(name = "Customers")
@Entity
public class CustomersEntity extends BasicEntity {
      @Id
     @GeneratedValue(generator = "UUID")
     @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
     @Column(name = "CustomerId", updatable = false, nullable = false, columnDefinition = "BINARY(16)")
     private UUID customerid;

     //and some other fields
}

没有它customer_id 列使用 256 字节(在 MySQL 中),这很可能导致 UUID 方程在随后保存解释重复创建的同一实体对象时失败。

更多信息:Hibernate and UUID identifiers

【讨论】:

  • 感谢您的回复。我尝试添加更改。但我仍然可以看到添加了两行。我们使用的是 sql server 而不是 MySql。很抱歉没有在帖子中提及。请问有什么办法吗?
  • @ging 您是否尝试删除并重新创建表(如果您可以选择)?
  • 是的。我确实删除了表格并再次创建了表格。但没有运气@MartinBG
  • @ging 当customers_id 列设置为binary(16) 时,我无法在MySQL 上重新创建问题。那时我会尽量简化设置——用一个简单的实体进行测试(没有继承,只有一个 id,默认的 equals 和 hashCode 方法),尝试使用 Long 类型的 id,也许在一个新的实体中完成所有这些项目来限制噪音。我有一个简单的项目,如果你想在那里测试,我可以上传到 github。
  • 尝试了大部分事情。通过重新创建表,每次都尝试使用 longId,没有继承和默认的 equals 和 hashcode。但是没有运气,但我仍然可以看到创建了两行 :( 你想让我尝试的任何其他想法或建议吗?任何其他 OnetoMany 或 ManyToMany 关系可能在这里产生影响?@MartinBG
猜你喜欢
  • 1970-01-01
  • 2020-06-24
  • 2020-12-22
  • 1970-01-01
  • 2012-10-13
  • 2020-08-12
  • 2017-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多