处理休眠实体上的数据库视图的优雅方法?

2022-09-01 17:29:02

我使用Hibernate的主要原因之一是它提供了切换到另一个数据库的灵活性,而无需重写任何代码。

但直到现在,我还没有找到一个好方法来定义与我的休眠实体匹配的表上的其他视图;我仍然使用简单的SQL脚本。有没有一种更优雅的方法来定义由休眠管理的表的视图?

理想情况下,我想使用HQL或其他通用方法来完成工作,这样我就不必担心我的SQL脚本与其他类型的数据库不兼容。

如果有一种方法可以做到这一点,那么第二个问题就是从这些视图中获取“合成”只读实例,这应该可以更容易地将聚合数据馈送到UI中。

编辑:

似乎我没有把问题说得足够清楚,所以这就是我要做的:我想编写独立于所用数据库的代码。由于我使用休眠,我只需要更改方言配置文件,然后就可以使用另一个DBMS。

问题:如何在不依赖特定 SQL 方言(以保持所有内容可移植性)甚至 HQL 的情况下在休眠实体上创建视图?如果可能,我是否可以使用 HQL 来查询这些视图,即创建只读聚合实体?是否有任何额外的休眠插件来帮助我做到这一点?到目前为止还没有找到任何东西... :-/


答案 1

Hibernate 不会自动为您创建视图,因为每种方言仅支持基础数据库的数据定义语言 (DDL) 的有限子集。基本上,它支持足够的DDL来生成工作架构,但不足以处理“额外”对象(如视图)的创建。

不过,一切都没有丢失。Hibernate 确实使您能够在 XML 映射文件中自己创建(和删除)其他数据库对象,并且这些对象的范围可以限定为特定的方言。例如,我可以有一个这样的映射:

<hibernate-mapping>
  <class name='com.mycompany.myproduct.Customer' table='tbl_customer'>
    <id name='id' column='customer_id'>
      <generator class='native'/>
    </id>
    <property name='name' length='50' unique='true' not-null='true' />
  </class>

  <database-object>
    <create>create or replace view read_only_cust...</create>
    <drop>drop view read_only_cust</drop>
    <dialect-scope name='org.hibernate.dialect.Oracle9Dialect' />
  </database-object>
</hibernate-mapping>

您可以通过添加更多“数据库对象”部分来自由创建所需的任何其他视图。您必须自己为要支持的每个数据库编写 SQL (DDL),但由于它们的作用域限定为方言,因此 Hibernate 将仅针对在架构导出时选择的方言执行 SQL。


答案 2

有同样的问题,并在休眠中找到了以下解决方案:

对于休眠映射,视图和基表之间没有区别。这在数据库级别是透明的,尽管某些 DBMS 不能正确支持视图,尤其是在更新时。有时,您希望使用视图,但无法在数据库中创建一个视图(即使用旧模式)。在这种情况下,您可以将不可变和只读实体映射到给定的 SQL 子选择表达式:

<class name="Summary">
    <subselect>
        select item.name, max(bid.amount), count(*)
        from item
        join bid on bid.item_id = item.id
        group by item.name
    </subselect>
    <synchronize table="item"/>
    <synchronize table="bid"/>
    <id name="name"/>
    ...
</class>

https://docs.jboss.org/hibernate/stable/core/manual/en-US/html_single/#mapping-declaration


推荐