JPA 是不是支持映射到 sql 视图?

Posted

技术标签:

【中文标题】JPA 是不是支持映射到 sql 视图?【英文标题】:Does JPA support mapping to sql views?JPA 是否支持映射到 sql 视图? 【发布时间】:2010-10-13 06:35:51 【问题描述】:

我目前正在使用 Eclipselink,但我知道现在大多数 JPA 实现已经非常标准化。是否有将 JPA 实体映射到视图的本地方法?我不打算插入/更新,但问题实际上是如何处理 @Id 注释。 JPA 世界中的每个实体都必须有一个 ID 字段,但是我创建的许多视图并不符合这一点。 JPA 中是否有对此的本机支持,或者我是否需要使用 hack 来使其工作?我进行了很多搜索,但发现关于这样做的信息很少。

【问题讨论】:

视图功能与普通表一样,但是如果您的视图不适合 JPA ORM 映射,您可以改为使用存储过程来返回由视图形成的自定义游标。您可以使用 @NamedStoredProcedureQuery 注释在 EclipseLink 中映射存储过程。有关此 Google 的“EclipseLink 扩展”的更多信息。 【参考方案1】:

虽然使用带有直接支持类型的字段的 @Id 注释并不是指定实体身份的唯一方法(请参阅带有多个 @Id 注释的 @IdClass 或带有 @Embedded@EmbeddedId),JPA 规范每个实体都需要一个主键。

也就是说,您不需要实体就可以将 JPA 与数据库视图一起使用。由于从 SQL 角度映射到视图与映射到表没有什么不同,因此您仍然可以使用本机查询(EntityManager 上的createNativeQuery)来检索标量值。

【讨论】:

JPA 库截至 2020 年 10 月抛出运行时异常“不是托管实体”【参考方案2】:

我自己一直在研究这个,我发现了一个我不是 100% 确定作品但看起来很有希望的 hack。

在我的例子中,我在视图中有一个 FK 列,它可以有效地充当 PK —— 该外来对象的任何给定实例只能在视图中出现一次。我从一个字段中定义了两个对象:一个被指定为 ID,代表字段的原始值,另一个被指定为只读,代表被引用的对象。


@Id
@Column(name = "foreignid", unique = true, nullable = false)
public Long getForeignId() 
...

@OneToOne
@JoinColumn(name = "foreignid", insertable=false, updatable=false)
public ForeignObject getForeignObject() 
...

就像我说的,我不能 100% 确定这个答案(如果它不起作用,我会删除这个答案),但它让我的代码超过了一个特定的崩溃点。

不知道它是否适用于您的具体情况。而且很有可能在 11 个月后,您不再关心。 :-) 什么鬼,“死灵法师”徽章不只是靠自己挣来的......

【讨论】:

【参考方案3】:

在我看来,我有一个“唯一”的 id,所以我将它映射为实体 id。 效果很好:

@Entity
@Table(name="table")
@NamedQuery(name="Table.findAll", query="SELECT n FROM Table n")
public class Table implements Serializable 
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="column_a")
    private int columnA;

【讨论】:

【参考方案4】:

JPA - 2.5.4

    CREATE MATERIALIZED VIEW IF NOT EXISTS needed_article as select  product_id, count(product_id) as count from product_article group by product_id;
    CREATE MATERIALIZED VIEW IF NOT EXISTS available_article as select product_id, count(product_id) as count from article a inner join  product_article p
                                on  a.id = p.article_id and a.stock >= p.amount_of group by product_id;
    
    CREATE UNIQUE INDEX productId_available_article ON available_article (product_Id);
    CREATE UNIQUE INDEX productId_needed_article ON needed_article (product_Id);

Entity.java

@Entity
@Immutable // hibernate import
@Getter
@Setter
public class NeededArticle 
    @Id
    Integer productId;
    Integer count;

Repository.java

@Repository
public interface AvailableProductRepository extends CrudRepository<AvailableArticle, Integer> 

    @Query("select available.productId from AvailableArticle available, NeededArticle needed where available.productId = needed.productId and available.count = needed.count")
    List<Integer> availableProduct();

【讨论】:

以上是关于JPA 是不是支持映射到 sql 视图?的主要内容,如果未能解决你的问题,请参考以下文章

JPA 支持没有对象关系映射的外部连接

将 MySql 视图映射到 JPA 实体,使用哪个唯一 ID?

Mybatis JPA

Mybatis/Hibernate/Spring Data Jpa选型对比

在 JPA/Hibernate 中持久化映射到 MySQL 视图的实体

springdataJpa对无主键表或视图查询的支持