6

我有两个类,Person 和 Company,派生自另一个类 Contact。它们在两个表(Person 和 Company)中以多态形式表示。简化的类如下所示:

public abstract class Contact {

  Integer id;

  public abstract String getDisplayName();

}

public class Person extends Contact {

  String firstName;
  String lastName;

  public String getDisplayName() {
    return firstName + " " + lastName;
  }

}

public class Company extends Contact {

  String name;

  public String getDisplayName() {
    return name;
  }

}

问题是我需要进行查询,以查找包含特定字符串的 displayName 的所有联系人。我无法使用 displayName 进行查询,因为它不是任一表的一部分。关于如何进行此查询的任何想法?

4

3 回答 3

4

因为您在 Java 类中进行连接,所以 Hibernate 无法真正帮助您完成这一点,抱歉。它根本看不到您在此方法中在做什么,因为它实际上与持久性无关。

解决方案取决于您如何映射这些类的继承:

如果是按层次结构的表,则可以使用以下方法:为条件查询编写 SQL where 子句,然后使用 case 语句:

s.createCriteria(Contact.class)
 .add(Restrictions.sqlRestriction("? = case when type='Person' then firstName || ' '|| lastName else name end"))
 .list();

如果它是每个具体子类的表,那么你最好编写两个查询(因为这是 Hibernate 无论如何都会做的)。

于 2009-06-12T19:06:16.860 回答
2

Contact您可以在包含相应 的表中创建一个新列displayName,您可以通过 Hibernate Interceptor填充该列,以便它始终自动包含正确的字符串。

另一种方法是有两个查询,一个针对 the Person,一个针对Company表,每个查询都包含各自的搜索逻辑。您可能必须使用本机查询来通过 LIKE 查询来查找连接的字符串(不过,我不是 HQL 专家,但很有可能)。

如果你有大表,你应该考虑全文索引,因为LIKE '%...%'查询需要全表扫描,除非你的数据库支持全文索引。

于 2009-06-12T10:57:37.207 回答
1

如果您将 displayName 更改为映射属性(在 Company 中设置为 name 列,在 Person 中设置为 first||' '||last 之类的公式),则可以查询 Contract,Hibernate 将运行两个查询,这两个查询现在都有一个显示名称。您将返回一个包含两个列表的列表,一个包含公司,一个包含人员,因此您必须将它们重新合并在一起。我认为您需要通过 Contract 的完整包名称查询或设置一个 typedef 来告诉 Hibernate。

于 2009-06-12T13:51:17.443 回答