【问题标题】:How to map a database view without a primary key when using JPA使用 JPA 时如何映射没有主键的数据库视图
【发布时间】:2015-09-26 07:51:03
【问题描述】:
  • 我在 SQL 数据库中有没有明显主键(复合或其他)的视图
  • 我想通过 JPA 访问它们

我读到我应该能够像对待表一样对待 JPA 中的视图(使用 @Table 注释等)。但是,如果没有主键,我必须有效地从每一列中生成一个复合键(事实上,这是 Hibernate 的逆向工程工具默认执行的操作)。

但是,如果我这样做,会有不良的副作用。 例如

  • 必须编写所有指向主键属性而不是视图的代码:

    myViewObject.getPrimaryKey().getFirstName()

  • 无法在 spring 存储库上使用“findBy...”方法(因为该属性是视图“标识符”的一部分,而不是它的属性之一)。

    李>

我的问题是:如何在这样的环境中映射视图,因为我可以使用 JPA 轻松访问它们的属性?

注意:我很高兴被告知我使用了完全错误的方法。这似乎是一个常见的问题,一定会有更好的解决方案。

【问题讨论】:

  • 我采用的一个技巧是分析视图上可能的查询,以查看有多少有可能返回多条记录,并查看在所有这些情况下是否存在对所有记录保持唯一的字段。如果你能找到这样的场景,你可以将该字段指定为主键,即使它不是真正的主键,因为 ORM 只关心单个查询结果之间的唯一性。但请注意,您将无法使用二级缓存。如果此技巧不适用,我会修改视图的查询以包含主键。
  • 没有什么可以阻止您编写诸如 getFirstName() 之类的委托方法,而 return this.getPrimaryKey().getFirstName()。然后你只需要写一次长版本。至于错误的方法,我们的应用程序中有超过 400 个实体/表,我们没有一个视图实体。我尝试使用一次,因为我认为它会有所帮助,但它开始引起问题,所以我在 JPQL 中创建了相同的“视图”,它完成了同样的工作,并且给了我更多的灵活性。

标签: java spring hibernate jpa sql-view


【解决方案1】:

您可以将UUID 列添加到视图的每一行,这样您就可以将 UUID 列用作@Id

【讨论】:

  • 是的,这行得通,谢谢。我已经更改了我的(Oracle)视图以包含一个额外的列:sys_guid() AS uuid 然后将以下属性添加到我的视图顶部@Entity:@Id @Column(name="UUID") @JsonIgnore protected String uuidHex;
  • 安迪,我认为解决方案的实施是错误的。每个查询的 UUID 都会不同。基本上它是一个有效的 id,但我不希望能够通过给定的 UUID 多次选择实体 A,即。您将无法从实体列表导航到单个实体。因此,该 UUID 应该是其中一个基表的一部分,并且实际上存储为列,而不是在视图中计算。另一种方法是使用物化视图。
  • 恰恰相反,这正是我解决问题所需要的。我的问题是没有明显的主键(见上文)。想象一个纯数据列的集合,其中一些或全部可能为空(在 SQL 数据库中足够典型)。我不得不人为地给他们一个PK来保持冬眠快乐。将生成的 UUID 添加到查询满足此条件。导航从一开始就不是一种选择。
  • @Immutable 添加到实体也可以吗?想象一下,您无权访问视图,需要将其映射到实体,然后添加 @Immutable 会起作用吗?
  • @MohammadEghlima:不,你会得到一个org.hibernate.AnnotationException: No identifier specified for entity: <entity> 错误。
猜你喜欢
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
  • 2018-07-11
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
相关资源
最近更新 更多