我有一个实体,我们称它为Policy
。 Policy
由 PolicyHolder
持有。不是所有的人一次,只有一个,但他们可以随着时间的推移而改变。我可以使用 @OneToMany
注释轻松地将 PolicyHolder
映射到策略。但是其中一位持有人很特别,因为它是当前持有人。我需要特殊的、很可能是 transient 的、可以保留其引用的字段。
其中一个问题是没有严格的鉴别器来区分当前持有者和其他持有者。找出其中哪一个是这个特殊的唯一方法,我需要在添加 holder 时找到最新的附件。理论上可以通过查询和子查询轻松完成:
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
,始终至少有一个 policy holder
。我尝试将列设置为 nullable = false
(我知道 - 它用于模式生成)和 optional = false
。但没有任何结果。
有什么想法吗?
最佳答案
我有类似的情况,我也无法让 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() 并且它还会返回一行
关于java - 带有公式的 Hibernate @OneToOne - 列不能外部连接到子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31251034/