1

我想在 HQL 中使用我的“where”子句中的抽象方法的结果。这可以做到吗?

像这样的东西:

@NamedQuery(name="getMailRelations", query="Select mr from MailRelation mr where mr.getOccurrences() > 5"

我有一个像这样的映射超类

@Entity
@Table(name="Mail_Entity", schema="relations")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="relationType", discriminatorType=DiscriminatorType.STRING)
@PersistenceContext(name="domas")
public abstract class MailRelation {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;

@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST})
@JoinColumn(name="mailId", referencedColumnName="mailId", nullable=false)
private Mail mail;

public void setMail(Mail mail) {
    this.mail = mail;
    if(!mail.getMailRelations().contains(this))
            mail.addMailRelation(this);
    }

public abstract int getOccurrences();

    public Mail getMail() {
        return mail;
   // and more code......
4

2 回答 2

2

不,那是不可能的。HQL 代码被翻译成 SQL 并在数据库上执行。通常 Java 方法不能被翻译成 SQL,并且数据库没有任何访问你的 Java 代码的权限。

如果你有这样的问题,例如有这三种可能性来处理它。这些可能性都不是完美的。

1)您使用 WHERE、GROUP BY 和 HAVING 在 HQL(或 SQL)中编写方法的逻辑。在您的示例中,getOc​​currences() 方法似乎返回了许多行,这可能可以通过“HAVING COUNT(...) > 5”来处理。

2)您使用数据库存储过程。这些是 p。前任。用 PL/SQL 编写的过程(在 Oracle 的情况下)。它们可以在 select 语句中访问。但是您失去了所选数据库的独立性。

3) 您加载了比需要更多的行并稍后在 Java 代码中进行过滤。

于 2012-05-08T14:46:40.837 回答
0

解决方案取决于您,但我添加了一些您可以考虑的其他选项:

如果您设法在所有情况下预先计算哈希,请使用参数化命名查询:

@NamedQuery(name="getMailRelations", query="Select mr from MailRelation mr where :occurrences > 5"

然后,您可以调用查询并添加参数“occurrences”:

String precalculatedHash = //your code here.
entityManager.createNamedQuery("getMailRelations",MailRelation.class).setParameter("occurrences", precalculatedHash).getResultList();

另一种选择是更深入地了解您的哈希逻辑,并确定您想用它实现什么。考虑到这一点,您可以使用Criteria API创建查询并添加该哈希表示的所有限制。这可能有点棘手,所以如果散列被证明过于依赖上下文(我的意思是如果它很大程度上依赖于你坚持的内容,以及你的应用程序的上下文),就放弃这个选项。

第三个选项是通过参数或Criteria API带来所有结果(或可能的最小结果集),并制作您的特定过滤逻辑。

于 2012-05-08T17:31:05.560 回答