Hibernate多态查询

我有两个类,Person和Company,来自另一个类Contact。 它们在两个表(Person和Company)中以多态forms表示。 简化的类看起来像这样:

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进行查询,因为它不是任何一个表的一部分。 关于如何进行此查询的任何想法?

因为你在Java类中进行连接,所以Hibernate无法真正帮助你解决这个问题,对不起。 它根本无法看到你在这个方法中做了什么,因为它实际上与持久性无关。

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

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

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

如果它是table per-concrete-subclass,那么你最好编写两个查询(因为这就是Hibernate无论如何都要做的)。

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

替代方案是有两个查询,一个用于Person ,一个用于Company表,每个查询包含相应的搜索逻辑。 您可能必须使用本机查询来实现通过LIKE查询查找连接字符串(我不是HQL专家,但很可能)。

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

如果你将displayName更改为一个映射属性(设置为公司中的名称列,并设置为像Person中最后一个||’|| last的公式),那么可以查询Contract和Hibernate将运行两个查询,这两个查询现在都有一个displayName。 您将获得两个列表的列表,一个包含公司,一个包含人员,因此您必须将它们合并在一起。 我认为您需要通过Contract的完整包名来查询,或者设置一个typedef来告诉Hibernate它。