【问题标题】:Persisting to SQL Server 2008 using stored procedures, JPA and Hibernate使用存储过程、JPA 和 Hibernate 持久化到 SQL Server 2008
【发布时间】:2009-11-18 09:30:57
【问题描述】:

我们正在实施一个网页来维护组织结构。该结构存储在 SQL Server 2008 中并使用新的 HierarchyID 数据类型。因为我们在让 JPA 和 Hibernate 使用这种新数据类型时遇到了问题,所以我们决定使用视图和存储过程来抽象出这种数据类型。因此,我们想使用存储过程来持久化我们的实体,但您如何使用 JPA 来做到这一点尚不清楚。

首先,我们是否采用了正确的方法,其次,是否可以使用存储过程来持久化使用 JPA 注释的实体?

【问题讨论】:

    标签: java sql-server hibernate orm jpa


    【解决方案1】:

    首先,我们是否采取了正确的方法 [...]

    嗯,这取决于。如果您不介意与您的数据库引擎绑定,那么我想希望从 HierarchyID 等专有功能中受益并不是完全错误的。但您不必必须使用新功能...

    其次,是否可以使用存储过程来持久化使用 JPA 注释的实体?

    据我所知,没有。您可以使用“本机查询”(请参阅​​@NamedNativeQuery 和/或EntityManager#createNativeQuery())调用存储过程,但不能使用它们来持久化实体,至少不能使用 JPA。如果您不介意使用 Hibernate 扩展,请查看 @SQLInsert(callable=true, ...)(参见 Hibernate Annotations 文档的 2.4.11. Custom SQL for CRUD operations 章节)。


    就个人而言,我发现创建视图、存储过程和处理 JPA 扩展只是为了使用 HierarchyID 非常麻烦。新功能很酷......当它们确实简化了事情时,而不是当它们增加更多复杂性时,就是这里的情况。换句话说,因为使用HierarchyID 并不能真正解决任何问题,我想我宁愿坚持使用经典的parent_id 列(这将使更改数据库引擎的过程更顺畅,即使这是不太可能的事件)。

    【讨论】:

    • 以上所有内容都大+1;它不仅仅是插入/更新 - 处理 HierarchyID 的 any 查询必须编写为 SQL。似乎麻烦多于它的价值。顺便说一句 - parent_id 不是映射层次结构的方法:-)
    • @ChssPly76 非常感谢 :) 对于我的文化,我对父/子层次结构缺少什么?我现在很怀疑,但在docs.jboss.org/hibernate/core/3.3/reference/en/html/… 中找不到答案。让我知道,以便我修复那部分。
    • 哦,它不是特定于休眠的。通过parentId 映射层次结构称为“邻接列表模型”。它在某些特殊情况下有其用途,但总体而言效率很低。 “嵌套集模型”可以说是一种更好的方法,尽管在“移动”操作上更复杂且性能更低。您可以谷歌任何一个以了解更多详细信息。
    【解决方案2】:

    我们已经确定了一种方法,当我们需要处理层次 ID 数据类型时,我们使用本机查询来调用存储过程。这使我们能够避免使用任何专有 SQL,同时仍然获得新数据类型的好处。

    我们的理解和初步发现是,层次 ID 允许我们通过简单地请求给定节点的所有后代来跨树结构聚合数据。

    例如,要对区域、办公室、商店和部门的“n”深度结构中的所有订单进行计数,可以使用以下内容:

    SELECT COUNT(Orders) FROM Orders WHERE NodeOrderedAt.IsDescendantOf(@Node)
    

    @ChssPly76 感谢您对这两个模型的引用。我稍后会读那些:)

    【讨论】:

      【解决方案3】:

      您可以使用@Pascal 建议的内容,也可以使用

      @org.hibernate.annotations.NamedNativeQuery(
           callable=true,
           name="queryname",
           readOnly=true,
           query="call sproc_name(?,:param)",
           resultSetMapping="your_result_mapping"
      )
      

      请参阅javadoc 了解完整的选项列表

      这种方法的唯一问题是out参数(如果你需要的话)必须是第一个并且必须输出一个refcursor。

      另见this(它指的是函数,但可以针对存储过程进行修改)。这些示例基于 Oracle,但调用字符串很容易针对 MSSQl 进行修改。

      我不太了解 HierarchyId 是否可以表示为 Hibernate UserType 或任何类型?

      【讨论】:

      • 我提到了本机查询,但是...这并不能回答 是否可以使用存储过程来 persist 用 JPA 部分注释的实体.
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 2017-04-09
      • 2023-04-08
      • 2012-02-03
      • 2011-04-02
      • 2015-01-26
      相关资源
      最近更新 更多