代码之家  ›  专栏  ›  技术社区  ›  Ricardo Marimon

休眠多态查询

  •  5
  • Ricardo Marimon  · 技术社区  · 15 年前

    我有两个类,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进行查询,因为它不是这两个表的一部分。关于如何进行这个查询有什么想法吗?

    3 回复  |  直到 11 年前
        1
  •  4
  •   Maarten Winkels    15 年前

    因为您在Java类中进行连接,所以Hibernate无法真正帮助您使用这一个,抱歉。它根本看不到您在这个方法中所做的事情,因为它实际上与持久性完全无关。

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

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

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

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

        2
  •  2
  •   Henning    15 年前

    您可以在 Contact 包含各自的 displayName ,您可以通过休眠来填充 Interceptor 所以它总是自动包含正确的字符串。

    另一种选择是有两个查询,一个用于 Person 一个 Company 表,每个表包含各自的搜索逻辑。您可能需要使用本机查询通过类似的查询来查找连接的字符串(不过,我不是HQL专家,这很有可能)。

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

        3
  •  1
  •   Brian Deterling    15 年前

    如果将DisplayName更改为映射属性(设置为公司中的“名称”列和“First”“Last-In-Person”等公式),则“Can Query for Contract”和“Hibernate”将运行两个查询,这两个查询现在都有一个DisplayName。您将得到一个包含两个列表的列表,一个包含公司,另一个包含人员,因此您必须将它们重新合并到一起。我认为您需要按合同的完整包名称进行查询,或者设置typedef来告诉Hibernate。