当前位置: 首页 > 知识库问答 >
问题:

如何避免Spring Data JPA/Hibernate生成的数据库中的id冲突?

张积厚
2023-03-14

我们使用一个停靠的postgres数据库,并让hibernate自动生成用于集成测试的表(使用spring.jpa.hibernate.ddl-auto:create)。使用H2之类的东西不是一种选择,因为我们在少数地方执行一些特定于数据库的操作,例如原生SQL查询。

当所有实体都使用自动递增的id时,有什么方法可以避免id冲突吗?或者通过抵消起始id,或者更好的是让所有表使用共享序列?

模式是在docker容器启动时创建的,表是由Spring数据JPA/Hibernate创建的

示例使用kotlin语法,并假设“allopen”插件应用于实体。

有时,在使用错误的外键时会出现错误,例如:

@Entity
class EntityOne(
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id", nullable = false, columnDefinition = "SERIAL")
  var id: Long,
)

@Entity
class EntityTwo(
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id", nullable = false, columnDefinition = "SERIAL")
  var id: Long,
)

@Entity
class JoinEntity(
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id", nullable = false, columnDefinition = "SERIAL")
  var id: Long,

  @ManyToOne
  @JoinColumn(name = "entity_one_id")
  var entityOne: EntityOne,

  @ManyToOne
  @JoinColumn(name = "entity_two_id")
  var entityTwo: EntityTwo,
)

@Repository
interface JoinEntityRepository : JpaRepository<JoinEntity, Long> {
  //
  // Bug here! Should be "WHERE entityOne.id = :entityOneId"
  //
  @Query("SELECT entityTwo FROM JoinEntity WHERE entityTwo.id = :entityOneId")
  fun findEntityTwoByEntityOneId(entityOneId: Long): Collection<EntityTwo>
}

在某些情况下,这些bug可能很难找到,因为在创建表时,很可能有一个Entity2与某个Entity1具有相同的id,因此查询成功,但测试失败,因为当它返回一个或多个Entity2时,它不是预期的。

更糟糕的是,根据测试的范围,即使提取了错误的实体,它也可能通过,或者只有在测试按特定顺序运行时(由于ID“不同步”)才会失败。因此,理想情况下,当传递错误的id时,它甚至应该找不到实体。但由于数据库结构是从头创建的,并且ID是自动递增的,所以它们总是从1开始。

共有1个答案

曹臻
2023-03-14

我找到了解决办法。

在我的资源/应用程序中。yml(在测试文件夹中,您很可能不想在主文件夹中执行此操作)我添加了spring。数据源。初始化模式:始终为文件和数据。sql。

数据的内容。sql如下:

DROP SEQUENCE IF EXISTS test_shared_sequence;
CREATE SEQUENCE test_shared_sequence;
ALTER TABLE entity_one ALTER COLUMN id SET DEFAULT nextval('test_shared_sequence');
ALTER TABLE entity_two ALTER COLUMN id SET DEFAULT nextval('test_shared_sequence');

Spring自动生成表后(使用spring.jpa.hibernate.ddl-auto: create),它将运行此脚本中的任何内容,并且脚本将更改所有表以基于相同的序列自动生成id,这意味着无论它们存储在哪个表中,都不会有两个实体具有相同的id,因此任何在错误表中查找id的查询都会一致失败。

 类似资料:
  • 问题内容: 某些数据库功能(例如和)很容易受到死锁的影响,因为数据库未指定将使用哪种锁定顺序。我发现有两次 讨论暗示此行为不是SQL标准指定的,更不用说具体的实现了。因此,我在假设我们无法控制锁定顺序的情况下进行操作(至少,这样做并不明显)。 如果我们不能依赖锁定顺序,应该如何避免数据库死锁? 如果我们不应该避免僵局(您将不得不非常努力地说服我),那么我们应该怎么做? 这个问题与数据库无关,所以请

  • 我试图在Laravel中加入3个表后查看特定表的日期。但是它只显示一个表的信息。 下面是连接3个表的代码: 路由文件: 下面是查看刀片模板中信息的脚本 刀片中的代码: 这里我想查看发票的创建日期,但它显示了subscribers表中订户的创建日期。但我想从发票表中查看发票的具体日期。 我该怎么做?当做

  • 我目前正在开发一个Android应用程序,我使用Firebase(实时功能)作为后端服务。此外,我开发了这个功能,如下所示。 扩展代码工作得很好,它检查现有数据并显示Toast消息,但在数据仍进入数据库后,我想消除重复数据。

  • 问题内容: 最近,我被分配创建拍卖系统的任务。在我的工作中,我遇到了无数次由于列名不明确而导致包含联接的SQL查询无法执行的情况。考虑以下(简化的)拍卖表结构: 表: (创建拍卖的用户的ID) 表: (添加项目的用户的ID) (有该物品的拍卖的ID) (初始价格) 表: 表: (出价的用户的ID) (已提高价格的项目) (优惠价格) 如您所见,有许多列具有冲突的名称。连接这些表需要采取一些措施来消

  • 设置了hibernate的Id生成策略,但是现在要存放指定的Id,要怎样才能 防止被hibernate自动生成的id覆盖? 关闭生成策略,但是现在要开启生成策略。

  • 我有一个Spring批处理作业,它从DB读取并写入CSV。批处理作业正在尝试使用我正在从中读取的数据库来保存批处理的状态。我不希望这种事发生。我正在使用Spring4。 经过大量的搜索,我尝试了两种方法,但都失败了。 方法1: null 我得到的例外情况如下。虽然例外并不是一个节目停止,我想摆脱它。 错误日志: