使用公式休眠@OneToOne - 列不能外连接到子查询

Posted

技术标签:

【中文标题】使用公式休眠@OneToOne - 列不能外连接到子查询【英文标题】:Hibernate @OneToOne with formula - A column may not be outer-joined to a subquery 【发布时间】:2015-09-23 21:44:41 【问题描述】:

我有一个实体,我们称之为PolicyPolicyPolicyHolders 持有。不是一次全部,只有一个,但它们可以随着时间的推移而改变。我可以使用 @OneToMany 注释轻松地将 PolicyHolders 映射到策略。但是其中一位持有者很特别,因为它是当前持有者。我需要特殊的、很可能是瞬态的字段,它可以保留其引用。

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

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】:

我也有类似的情况,我也无法让 hibernate 生成内部连接。不幸的是,外连接不能用子查询完成(正如你已经注意到的)。所以我的解决方案虽然不是最好的,但还是在 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;

我知道这是一种解决方法,但在我的场景中效果很好。如果它是一个函数,hibernate 知道它只会返回一行。否则它不会评估查询以查看您是否添加了 max() 并且它也会返回一行

【讨论】:

以上是关于使用公式休眠@OneToOne - 列不能外连接到子查询的主要内容,如果未能解决你的问题,请参考以下文章

休眠 | Spring Data JPA | @OneToOne

休眠 @OneToOne 与 Principal REST 的映射

Hibernate @OneToOne 映射不加入列?

Spring - 使用休眠和弹簧安全扩展类

TypeOrm OneToOne 关系导致不需要的列嵌入

hibernate/jpa double OneToOne 与一个实体的双向关系