带有公式的Hibernate @OneToOne - 列可能不是外部连接到子查询

时间:2015-07-06 16:30:36

标签: java oracle hibernate formula outer-join

我有一个实体,我们称之为PolicyPolicy持有PolicyHolder。并非所有这些都只是一次,但它们可以随着时间而改变。我可以使用PolicyHolder注释轻松地将@OneToMany映射到策略。但是其中一个持有者是特殊的,因为它是现在的。我需要特殊的,最可能是瞬态的,可以保持其参考。

其中一个问题是没有严格的鉴别器来区分当前持有人与其他持有人。找出其中哪一个是特殊的唯一方法,我需要在添加持有人时找到最新的附件。从理论上讲,它可以通过查询和子查询轻松完成:

SELECT * FROM holders h 
WHERE h.policy_id = :myPolicyId AND h.annex_id = 
(SELECT MAX(annex_id) FROM holders sh WHERE sh.policy_id = h.policy_id)

将字段PolicyHolder映射为使用@JoinColumnOrFormulas注释的字段似乎是个好主意。我试过这样的话:

public class Policy {

    @OneToMany(...)
    private Set<PolicyHolder> holders;

    @ManyToOne
    @JoinColumnOrFormulas({
      @JoinColumnOrFormula(
        column = @JoinColumn(columnName = "policy_id", referencedColumnName = "policy_id")),
      @JoinColumnOrFormula(
        formula = "SELECT MAX(annex_id) FROM holders h WHERE h.policy_id = policyId", 
        referencedColumnName = "annex_id")      
      )
    })
    private PolicyHolder currentHolder;
}

我甚至不知道上面这段代码是否有效。我现在无法检查它,它是用记事本写的。无论如何,它以Hibernate生成正确查询的方式为我工作。但查询没有在Oracle数据库上执行,并显示错误消息:A column may not be outer-joined to a subquery(为什么?)。

好的,所以我试图强制Hibernate生成内连接而不是外连接。这是安全的,因为policy holder始终至少有一个policy。我尝试将列设置为nullable = false(我知道 - 它用于架构生成)和optional = false。但没有任何结果。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我有类似的情况,也无法使休眠生成内部联接。不幸的是,无法通过子查询完成外部联接(如您所知)。所以我的解决方案虽然不是最好的解决方案,但还是在oracle中创建了一个函数。然后它将变为:

 @ManyToOne
@JoinColumnOrFormulas({
  @JoinColumnOrFormula(
    column = @JoinColumn(columnName = "policy_id", referencedColumnName = "policy_id")),
  @JoinColumnOrFormula(
    formula = "getMaxAnnexForPolicy(policyId)", 
    referencedColumnName = "annex_id")      
  )
})
private PolicyHolder currentHolder;

并创建一个函数,例如:

CREATE OR REPLACE Function getMaxAnnexForPolicy
   ( policyId in varchar2)
   RETURN varchar2
IS
   res varchar2(200);
BEGIN
 SELECT MAX(annex_id) into res FROM holders h WHERE h.policy_id = policyId;
RETURN res;
end getMaxAnnexForPolicy;

我知道这是一种解决方法,但在我的情况下效果很好。如果它是一个函数,休眠知道它将仅返回一行。否则,它不会评估查询是否看到您已添加max(),并且还会返回一行