Использование Hibernate Search более 2 дочерних элементов с общим свойством - PullRequest
2 голосов
/ 25 января 2011

У меня есть следующая модель данных:

@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 имеют одно и то же свойство "receiveName", у меня возникла проблема при поиске значения, скажем "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;
    }

Таким образом, после индексации сущностей и попытки выполнить поиск по «receiveName», которое является общим для моей базы данных, скажем «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

Я прочитал множество форумов поиска в спящем режиме и даже книгу «Поиск в спящем режиме» без каких-либо положительных результатов, кто-нибудь подскажет мне идеи или возможные решения этой проблемы? Спасибо

РЕДАКТИРОВАТЬ : Обнаружено, что проблема заключалась в том, что EntryDetail и EntryDetailCtx могут иметь одинаковые идентификаторы (поскольку оба находятся в разных таблицах ..), однако, поскольку @documentID наследуется из AbstractRecord может дублироваться в обеих таблицах, во время выполнения поиска возникает проблема ... Теперь у меня есть дополнительная проблема, и это следующее:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractRecord
    implements Serializable
{
    //~ Instance variables ---------------------------------------------------------------
/** SERIALID */ public static final String SERIALID = "hyzmfgSwl5hsDbxZIitNILMT2/eiPYJErJcqIMun3/PVy3SbbiQie4k9lLnL450BhwL8EnUMyc+wrhgZtUBTdG9/YUuJ+ni/FRAdRGzTy7UrQI7opbrYRYehDUwj3hg9";
    /** id for this record. */
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name = "id", nullable = false)
    private Integer id;

    /** line number for this record. */
    @Field(index=Index.UN_TOKENIZED, store=Store.NO)
    @Column(name = "record_number", nullable = false)
    private Integer recordNumber;

    /** record types for this record. */
    @Field(index=Index.UN_TOKENIZED, store=Store.NO)
    @Column(name = "record_type", nullable = false)
    private Integer recordType;

    /** Current status for this record. */
    @Field(index=Index.UN_TOKENIZED, store=Store.NO)
    @Column(name = "record_status", nullable = false)
    @Enumerated(EnumType.ORDINAL)
    private RecordStatus recordStatus;

    /** unique table key for the file. */
    @Field(index=Index.UN_TOKENIZED, store=Store.NO)
    @Column(name = "unique_table_key", nullable = false)
    private String uniqueTableKey;

    ...
}

Мне нужно, чтобы uniqueTableKey и recordNumber были моими новыми @ documentID для поиска, однако поиск в Hibernate допускает только 1 documentId, справка?

1 Ответ

0 голосов
/ 19 февраля 2011

Возможные решения этой проблемы следующие: EmbeededID а также Idclass

И затем аннотировать как @DocumentId любое из выбранных выше решений

...