我有两个类,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进行查询,因为它不是任何一个表的一部分。关于如何进行此查询的任何想法?
答案 0 :(得分:4)
因为你在Java类中进行连接,所以Hibernate无法真正帮助你解决这个问题,对不起。它根本无法看到你在这个方法中做了什么,因为它实际上与持久性无关。
解决方案取决于您如何映射这些类的继承:
如果是每层次表,您可以使用以下方法:为条件查询编写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无论如何都要做的)。
答案 1 :(得分:2)
您可以在Contact
表格中创建一个包含相应displayName
的新列,您可以通过Hibernate Interceptor填充该列,以便它自动包含正确的字符串。
替代方案是有两个查询,一个用于Person
,一个用于Company
表,每个查询包含相应的搜索逻辑。您可能必须使用本机查询来实现通过LIKE查询查找连接字符串(我不是HQL专家,但很可能)。
如果你有大表,你应该考虑全文索引,因为LIKE '%...%'
查询需要全表扫描,除非你的数据库支持全文索引。
答案 2 :(得分:1)
如果将displayName更改为映射属性(设置为公司中的名称列,并设置为类似于最后一个||''|| last in Person),则可以查询Contract和Hibernate将同时运行两个查询现在有一个displayName。您将获得两个列表的列表,一个包含公司,一个包含人员,因此您必须将它们合并在一起。我认为您需要通过Contract的完整包名来查询,或者设置一个typedef来告诉Hibernate。