使用带有共享属性的2个subclasess的Hibernate搜索

时间:2011-01-25 14:32:02

标签: hibernate lucene full-text-search hibernate-search

我有以下数据模型:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractRecord
    implements Serializable
{
    ...
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    @DocumentId
    private Integer id;
    ...

}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@NamedQueries(...)
})
public abstract class AbstractEntryDetail
    extends AbstractRecord
    implements Serializable
{
...
}

@Indexed(index = "entryDetailIndex")
@Entity
@Table(name = "nacha_entry_detail")
@NamedQueries(...)
})
public class EntryDetail
    extends AbstractEntryDetail
    implements Serializable
{
    ...
    @Field(index = Index.TOKENIZED, store = Store.NO)
    @Column(name = "receiver_name", nullable = false)
    private String receiverName;
    ...

}

@Indexed(index = "entryDetailCtxIndex")
@Entity
@Table(name = "nacha_entry_detail_ctx")
@NamedQueries(...)
public class EntryDetailCtx
    extends AbstractEntryDetail
    implements Serializable
{
    ...
    @Field(index = Index.TOKENIZED, store = Store.NO)
    @Column(name = "receiver_name", nullable = false)
    private String receiverName;
    ...
}

如您所见,EntryDetail和EntryDetailCtx共享相同的属性“receiverName”,我在通过以下代码搜索值“IndividualName1”时遇到问题:

@Stateless
@TransactionAttribute(TransactionAttributeType.MANDATORY)
@RolesAllowed({PermissionUtil.SEARCH_LIST,
    PermissionUtil.LUCENE_INDEX
})
public class SearchFacade
{
    ...
    @RolesAllowed(PermissionUtil.SEARCH_LIST)
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public List<AbstractRecord> doSearch(String stringToFind)
    {
        List<AbstractRecord> result = null;

        // Test Search for specific values of an Abstract Record
        // Aim to return the number of retreived results
        EntityManager em = emf.createEntityManager();
        FullTextEntityManager fullTextEntityManager =
            org.hibernate.search.jpa.Search.getFullTextEntityManager(em);
        String[] fields =
            // Fields to be reviewed
            new String[]
            {   ....,"receiverName",.... 
            };

        //Create a multi-field Lucene query
        StandardAnalyzer stdAnalyzer = new StandardAnalyzer(Version.LUCENE_30);
        MultiFieldQueryParser parser =
            new MultiFieldQueryParser(Version.LUCENE_30, fields, stdAnalyzer);
        org.apache.lucene.search.Query query = null;

        try
        {
            query = parser.parse(stringToFind);
        }
        catch (ParseException ex)
        {
            Logger.getLogger(SearchFacade.class.getName()).log(Level.SEVERE, null, ex);
        }

        long time1 = System.currentTimeMillis();

        // Wrap Lucene query in a javax.persistence.Query
        javax.persistence.Query persistenceQuery =
            fullTextEntityManager.createFullTextQuery(query);
        // Execute search
        //HAVING PROBLEMS HERE
        result = (List<AbstractRecord>) persistenceQuery.getResultList();

        long time2 = System.currentTimeMillis();
        Logger.getLogger(SearchFacade.class.getName())
              .log(
            Level.FINER, "Hibernate Search Execution time: {0}",
            Long.toString(time2 - time1));

        //em.getTransaction().commit();
        em.close();

        return result;
    }

因此,在对实体编制索引并尝试对我的数据库上共享的“receiverName”执行搜索之后,请说“Jhon”我得到以下异常..

Caused by: org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: com.xxx.ejb.core.entity.nacha.EntryDetailCtx (loaded object was of wrong class class com.xxx.ejb.core.entity.nacha.EntryDetail)
    at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:1391)
    at org.hibernate.loader.Loader.getRow(Loader.java:1344)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611)
    at org.hibernate.loader.Loader.doQuery(Loader.java:829)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    at org.hibernate.loader.Loader.doList(Loader.java:2533)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    at org.hibernate.loader.Loader.list(Loader.java:2271)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:119)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1716)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)
    at org.hibernate.search.engine.ObjectLoaderHelper.initializeObjects(ObjectLoaderHelper.java:116)
    at org.hibernate.search.engine.MultiClassesQueryLoader.executeLoad(MultiClassesQueryLoader.java:124)
    at org.hibernate.search.engine.AbstractLoader.load(AbstractLoader.java:70)
    at org.hibernate.search.query.FullTextQueryImpl.list(FullTextQueryImpl.java:317)
    at org.hibernate.search.jpa.impl.FullTextQueryImpl.getResultList(FullTextQueryImpl.java:137)
    at com.paysett.ejb.core.facade.SearchFacade.doSearch(SearchFacade.java:130)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1056)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1128)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5292)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:615)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:567)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:157)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:139)
    at sun.reflect.GeneratedMethodAccessor525.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:858)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:797)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:367)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5264)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5252)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:190)
    ... 52 more

我已经阅读了很多hibernate搜索论坛甚至Hibernate Search in Action一书,没有任何积极的结果,任何人都会想到这个问题的想法或可能的解决方案吗? 感谢

编辑 :发现问题是EntryDetail和EntryDetailCtx都有相同的ID(因为两者都在不同的表上......)但是{{1}继承自AbstractRecord的,可以在两个表中重复搜索执行时生成问题...现在我还有一个问题,它是以下内容:

@documentID

我需要uniqueTableKey和recordNumber作为我的新@ documentID用于搜索,但是Hibernate搜索只允许1个documentId,帮忙吗?

1 个答案:

答案 0 :(得分:0)

此问题的可能解决方案如下: EmbeededIDIdclass

然后注释为@DocumentId任何上述选择的解决方案