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

使用“纯”Hibernate/JPA同时更新唯一列中的多个条目

米嘉禧
2023-03-14

我有一个存储任务的表,还有一个存储该任务的有序步骤的表。步骤属于一个任务父级(因此一个任务与一个步骤具有一对多的关系),每个步骤都有一个“序号”--它是哪个步骤号。我希望序号和父任务ID是一个组合的唯一约束,因此,例如,单个任务永远不能结束两个不同的步骤设置为“Step1”,但不同的任务可以各自有自己的“Step1”。

我希望能够同时更新属于一个任务的每一步的序数,这样我就不会违反唯一约束。因此,如果我有“步骤1”、“步骤2”和“步骤3”,我可以在“步骤2”插入一个新的步骤,并将现有的步骤转换为“步骤3”和“步骤4”。我知道某些数据库允许您延迟检查约束,直到事务提交,但我非常希望能够避免任何需要特定数据库类型的操作,并且完全在JPA/Hibernate中完成此操作。

以下是我的实体的简化版本:

任务:

@Table
@Entity
public class Task {

    @Version
    private Long version;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Step> steps;
}

步骤:

@Entity
@Table(
    uniqueConstraints = {
        @UniqueConstraint(
            name = "UX_Step_Parent_Ordinal",
            columnNames = {"parent_id", "ordinal"})
    }
)
public class Step {

    @Version
    private Long version;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false, name = "ordinal")
    private Long ordinal;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "parent_id")
    private Task parent;
}

到目前为止,我想出的唯一方法是首先在末尾插入新步骤,然后动态生成一个HQL查询,该查询如下所示,它使用一个case立即更新特定任务中的每一个步骤:

UPDATE Step s
SET s.ordinal = CASE
 WHEN (s.id = 55) THEN 1
 WHEN (s.id = 58) THEN 2
 WHEN (s.id = 47) THEN 3
 WHEN (s.id = 33) THEN 4
 ... etc
 ELSE 0 END
WHERE s.parent.id = 5

但是,我非常肯定,这需要引擎在每次发生查询时重新处理查询,因此不能利用查询缓存或其他加速。对于Hibernate/JPA是否还有其他方法可以做到这一点?

共有1个答案

莫承运
2023-03-14

不确定它是否真的解决了问题,但我认为您应该将集合建模为一个映射:

@OneToMany
@MapKeyJoinColumn(Name="ordinal")
private Map<Long,Step> steps;

当您在中间添加一个步骤时,您有责任更新整个地图。

如果您还需要步骤中的序数,那么您必须使其为只读:

@Column(nullable = false, name = "ordinal", insertable=false, updateable=false)
private Long ordinal;
 类似资料:
  • 问题内容: 有没有一种方法可以使用JPA指定在不同的列集上应该有多个唯一约束? 我已经看到了特定于hibernate的注释,但是由于我们仍在确定hibernate和数据核之间的关系,因此我试图避免使用特定于供应商的解决方案。 问题答案: 所述的属性实际接受的这些阵列。您的示例只是具有单个元素的数组的简写。否则,它看起来像: 只要唯一性约束仅基于一个字段,就可以在该列上使用。

  • 问题内容: 我有两个模型。 什么JPA / Hibernate注解,我需要把上面,并且使协会工作? 当然,我尝试了很多事情,但没有任何效果。例如,设置 和 ald 。也尝试使用,但是只接受一个参数(不能这样做。 还考虑过将其移动到平板电脑上,但是我不确定OneToMany和ManyToOne的注释应该是什么样,因为我在那里有多个地址,而JoinColumns并没有多大意义。 起作用但未创建关联的事

  • 我有一个适用于Spring MVC和Hibernate的应用程序。如果单个用户插入一条记录,它可以正常工作,但如果多个用户同时插入记录。它显示此错误“Hibernate:org.hibernate.AssertionFailure: null id in”。我可以观察到这种情况正在发生,因为hibernate对所有记录的自动主id genaration可能是相似的,因为时间相同。不确定this.P

  • 问题内容: 我试图创建一个表,我需要它不允许3个字段相同的行。 当我使用SQLLite在Python中创建表时,使用了以下代码,但几乎没有得到任何结果。它通常在写入2条记录后停止,因此显然可以相信它是重复的。 因此,我希望数据库不允许在ownerID1,ownerID2,accountKey和argID1相同的记录。 谁能帮我这个忙吗? 谢谢! 问题答案: 我不确定是什么问题。它在这里工作正常:

  • 问题内容: 我想更新表的所有字段的值为“ PCNAME”。我要更新的表名是XYZ。我只想更新一些字段而不保留一些不变。 这会影响很多行而不是一行,因为会有很多行带有NAME =’PCNAME’。我如何使用JPA做到这一点。我有与此表关联的实体类。 问题答案: 您既可以采用面向对象的方式,也可以使用更新查询。 面向对象: 使用更新查询(未试用): 显然,第二个版本的性能更好。

  • 问题内容: 使用Hibernate的条件,我想执行以下操作: 我认为执行以下操作将产生想要的结果: 但是,这实际上是执行类似以下操作: 显然,这引发了错误。 除了不使用条件以外,还有解决方案吗? 谢谢, 布兰登 问题答案: