我有一个抽象类产品,它由 ProductA , ProductB 和 ProductC 分类。
ProductA , ProductB 和 ProductC 类映射到数据库表 PRODUCTS_A , PRODUCTS_B 和 PRODUCTS_C 。
现在我想通过Hibernate Search对 ProductA 实体进行全文搜索。
我写了一些代码来成功地从数据库中获得预期的 ProductA 实体,但是我在日志中发现(如下),执行的Hibernate Search查询实际上搜索了所有表 PRODUCTS_A , PRODUCTS_B 和 PRODUCTS_C ,而不仅仅是我预期的 PRODUCTS_A 表格。
我想只获得 ProductA 实体,为什么还搜索了 ProductB 和 PRODUCTS_C 表?有办法解决这个问题吗?
您可以从Hibernate输出的以下工作日志中看到,除 PRODUCTS_A 表外,还会搜索 PRODUCTS_B 和 PRODUCTS_C 表。
Hibernate:选择this_.ID作为ID1_2_0_,this_.NAME作为NAME2_2_0_,this_.FEATURE作为FEATURE3_2_0_,this_.CREATED_DATE作为CREATED_4_2_0_,this_.MODIFIED_DATE作为MODIFIED5_2_0_,this_.FEATURE_A1作为FEATURE_1_3_0_,this_.FEATURE_A2作为FEATURE_2_3_0_,this_。 FEATURE_B1为FEATURE_1_4_0_,this_.FEATURE_B2为FEATURE_2_4_0_,this_.FEATURE_C1为FEATURE_1_5_0_,this_.FEATURE_C2为FEATURE_2_5_0_,this_.clazz_为clazz_0_ from(选择ID,NAME,FEATURE,CREATED_DATE,MODIFIED_DATE,FEATURE_A1,FEATURE_A2,null :: varchar为FEATURE_B1 ,null :: varchar as FEATURE_B2,null :: varchar as FEATURE_C1,null :: varchar as FEATURE_C2,1 from clazz_ from PRODUCTS_A union all select ID,NAME,FEATURE, CREATED_DATE,MODIFIED_DATE,null :: varchar as FEATURE_A1,null :: varchar as FEATURE_A2,FEATURE_B1,FEATURE_B2,null :: varchar as FEATURE_C1,null :: varchar as FEATURE_C2,2 from clazz_ from PRODUCTS_B union all 选择ID,NAME,FEATURE,CREATED_DATE,MODIFIED_DATE,n ull :: varchar as FEATURE_A1,null :: varchar as FEATURE_A2,null :: varchar as FEATURE_B1,null :: varchar as FEATURE_B2,FEATURE_C1,FEATURE_C2,3 from clazz_ from PRODUCTS_C )this_ where(this_。 (?)中的ID
以下是实体类产品, ProductA , ProductB 和 ProductC 。
public abstract class Product {
@Id
protected Long id;
@Field
protected String name;
@Field
protected String feature;
protected Date createdDate;
protected Date modifiedDate;
// Getters and setters...
}
@Entity
@Indexed
public class ProductA extends Product {
@Field
private String featureA1;
@Field
private String featureA2;
public ProductA() {
}
// Getters and setters...
}
ProductB 和 ProductC 类与 ProductA 类相似。
Product.hbm.xml
union-subclass 元素用于反映 Product 类与 ProductA , ProductB 之间的子类关系, ProductC 类。
<hibernate-mapping package="com.raychen518.study.hibernate">
<class name="Product" abstract="true">
<id name="id" column="ID">
<generator class="increment" />
</id>
<property name="name" column="NAME" />
<property name="feature" column="FEATURE" />
<property name="createdDate" type="timestamp" column="CREATED_DATE" />
<property name="modifiedDate" type="timestamp" column="MODIFIED_DATE" />
<union-subclass name="ProductA" table="PRODUCTS_A">
<property name="featureA1" column="FEATURE_A1" />
<property name="featureA2" column="FEATURE_A2" />
</union-subclass>
<union-subclass name="ProductB" table="PRODUCTS_B">
<property name="featureB1" column="FEATURE_B1" />
<property name="featureB2" column="FEATURE_B2" />
</union-subclass>
<union-subclass name="ProductC" table="PRODUCTS_C">
<property name="featureC1" column="FEATURE_C1" />
<property name="featureC2" column="FEATURE_C2" />
</union-subclass>
</class>
</hibernate-mapping>
hibernate.cfg.xml中
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5432/test</property>
<property name="connection.username">postgres</property>
<property name="connection.password">admin</property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">validate</property>
<!-- Setting for Hibernate Search -->
<property name="hibernate.search.lucene_version">LUCENE_CURRENT</property>
<property name="hibernate.search.default.directory_provider">filesystem</property>
<property name="hibernate.search.default.indexBase">hibernate.search.test/lucene/indexes</property>
<mapping resource="Product.hbm.xml" />
</session-factory>
</hibernate-configuration>
ProductManager 类包含main方法,因此用作应用程序启动器。它启动Hibernate Search索引过程,清除 PRODUCTS_A , PRODUCTS_B 和 PRODUCTS_C 表,并将一些示例产品数据插入其中,最后执行使用Hibernate Search进行全文搜索 令我困惑的是,我在以下语句中将目标实体指定为 ProductA.class 查询查询中的查询= fullTextSession.createFullTextQuery(luceneQuery,ProductA.class); 的 searchProducts()即可。为什么Hibernate Search还会搜索 ProductB 和 ProductC 实体?
public class ProductManager {
public static void main(String[] args) throws InterruptedException {
ProductManager productManager = new ProductManager();
productManager.indexAllProducts();
productManager.deleteAllProducts();
productManager.generateSomeProducts();
productManager.searchProducts();
}
private void indexAllProducts() throws InterruptedException {
FullTextSession fullTextSession = Search.getFullTextSession(HibernateUtil.getSessionFactory().getCurrentSession());
fullTextSession.createIndexer().startAndWait();
}
public void deleteAllProducts() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
@SuppressWarnings("unchecked")
List<Product> results = session.createQuery("from Product").list();
for (Product result : results) {
session.delete(result);
}
session.getTransaction().commit();
}
public void generateSomeProducts() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(new ProductA("feature001", "featureA1001", "featureA2001", new Date()));
session.save(new ProductA("feature002", "featureA1002", "featureA2002", new Date()));
session.save(new ProductA("feature003", "featureA1003", "featureA2003", new Date()));
session.save(new ProductB("feature001", "featureB1001", "featureB2001", new Date()));
session.save(new ProductB("feature002", "featureB1002", "featureB2002", new Date()));
session.save(new ProductB("feature003", "featureB1003", "featureB2003", new Date()));
session.save(new ProductC("feature001", "featureC1001", "featureC2001", new Date()));
session.save(new ProductC("feature002", "featureC1002", "featureC2002", new Date()));
session.save(new ProductC("feature003", "featureC1003", "featureC2003", new Date()));
session.getTransaction().commit();
}
private void searchProducts() {
FullTextSession fullTextSession = Search.getFullTextSession(HibernateUtil.getSessionFactory().getCurrentSession());
fullTextSession.beginTransaction();
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(ProductA.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder.keyword().onFields("feature").matching("feature002").createQuery();
// Set the 2nd method parameter using "Product.class" to get products of the types ProductA, ProductB and ProductC.
// Set the 2nd method parameter using "ProductA.class" to get products of the types ProductA.
Query query = fullTextSession.createFullTextQuery(luceneQuery, ProductA.class);
@SuppressWarnings("unchecked")
List<Product> queryResults = query.list();
for (Product queryResult : queryResults) {
System.out.println("queryResult: " + queryResult);
}
fullTextSession.getTransaction().commit();
}
}
答案 0 :(得分:3)
我最近在另一个Stackoverflow问题后将其修复为https://hibernate.atlassian.net/browse/HSEARCH-2301。
它尚未发布,但补丁相当小,仅在一个文件中进行了本地化:https://github.com/hibernate/hibernate-search/pull/1122/files因此您应该可以在5.5分支上本地应用它。
使用https://patch-diff.githubusercontent.com/raw/hibernate/hibernate-search/pull/1122.diff获取原始差异文件。
更新我们已将其修复为5.5.4.Final:http://in.relation.to/2016/06/29/Polishing-Polishing-And-More-Polishing-Hibernate-Search-5-5-4-Final/