在 Hibernate 5.1 中通过自定义 SQL 查询定义实体

Define an entity via a custom SQL query in Hibernate 5.1

我正在使用非标准化的第 3 方数据库,这意味着我无法更改架构。我正在尝试使用 Hibernate 5.1

将 table 映射到 JPA 实体

有2个简单的tables A和B:

|  A_ID(pk) |      |  B_ID(pk) |
-------------      -------------
|    1      |      |    1      |
-------------      |    2      |
                   -------------

Table C 有复合主键并且与 Table A:

有多对一关系
|   A_ID(pk&fk)   | QUANTITY(pk) | VALID_FROM(pk) |
---------------------------------------------------
|     1           |      1       |  2017-05-21    |
|     1           |      1       |  2018-01-01    |
|     1           |      2       |  2017-05-21    |

Table D 有复合主键:

|   A_ID(pk&fk)   | QUANTITY(pk) | VALID_FROM(pk) |   B_ID(pk&fk)  | 
--------------------------------------------------------------------
|     1           |      1       |  2018-01-21    |     1          | 
|     1           |      2       |  2018-01-21    |     1          | 
|     1           |      2       |  2018-05-01    |     2          | 

VALID_FROM 列不是 table 之间的连接条件的一部分,可以占用任何值。

我正在尝试建立 Table C 和 D 之间的关系,但由于 VALID_FORM 主键组件,它们无法使用多对一建模。而且由于没有连接 table 它们也不能用多对多建模。

最好的解决方案是创建一个像

这样的视图
CREATE VIEW C_NORM AS
  SELECT DISTINCT A_ID, QUANTITY 
  FROM TABLE_C;

这将产生视图 C_NORM:

 |   A_ID(pk&fk)   | QUANTITY(pk) |
 ----------------------------------
 |     1           |      1       |
 |     1           |      2       |

在此视图上创建 C_NORM 实体可能

但我无法更改架构,因此无法创建新视图。

是否有任何方法可以将实体定义为 class 并带有基本上基于本机 SQL 查询而不是视图或 table 的注释在数据库中?

不,那不可能,也没有意义。

实体用于更新、插入和删除。如果您不想执行任何这些操作,则不应使用实体。

您可以使用 @SqlResultSetMapping 将本机查询的结果映射到 class

Query q = em.createNativeQuery(
    "SELECT c.id, c.name, COUNT(o) as orderCount, AVG(o.price) AS avgOrder " +
    "FROM Customer c " +
    "JOIN Orders o ON o.cid = c.id " +
    "GROUP BY c.id, c.name",
    "CustomerDetailsResult");

@SqlResultSetMapping(name="CustomerDetailsResult",
    classes={
    @ConstructorResult(targetClass=com.acme.CustomerDetails.class,
        columns={
            @ColumnResult(name="id"),
            @ColumnResult(name="name"),
            @ColumnResult(name="orderCount"),
            @ColumnResult(name="avgOrder", type=Double.class)})
})

或者使用 QLRM:https://github.com/simasch/qlrm