2013-08-30 3 views
1

У меня возникает странная проблема с Hibernate Search и Lucene. Я считаю, что эта проблема довольно простая: когда я ищу что-то, что возвращает более одной записи, все работает нормально. Когда я ищу что-то, возвращающее только одну запись, тогда элементы сущности имеют значение null, но когда я вызываю метод toString(), все есть.Hibernate Search/Lucene возвращает нулевые элементы, когда результат - одна запись

Мои Entity:

import java.io.Serializable; 
import java.sql.Blob; 

import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.Table; 

import org.hibernate.search.annotations.Analyze; 
import org.hibernate.search.annotations.Field; 
import org.hibernate.search.annotations.Index; 
import org.hibernate.search.annotations.Indexed; 
import org.hibernate.search.annotations.Store; 

@Entity 
@Indexed 
@Table(name = "vw_colaborador", schema = "col") 
public class Colaborador implements Serializable { 

    private static final long serialVersionUID = 886370076152195975L; 

    @Id 
    @Column(name = "id", insertable = false, updatable = false) 
    private Long id; 

    @Column(name = "matricula", insertable = false, updatable = false) 
    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    private String matricula; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "nome", insertable = false, updatable = false) 
    private String nome; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "email", insertable = false, updatable = false) 
    private String email; 

    @Column(name = "foto", insertable = false, updatable = false) 
    private Blob foto; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "login", insertable = false, updatable = false) 
    private String login; 

    @Field(store = Store.YES, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "ramal", insertable = false, updatable = false) 
    private String ramal; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "hierarquia_ua", insertable = false, updatable = false) 
    private String ua; 

    @Column(name = "situacao_id", insertable = false, updatable = false) 
    private Long situacaoId; 

    @Column(name = "situacao", insertable = false, updatable = false) 
    private String situacao; 

    @Column(name = "vinculo_id", insertable = false, updatable = false) 
    private Long vinculoId; 

    @Column(name = "vinculo", insertable = false, updatable = false) 
    private String vinculo; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "diretoria", insertable = false, updatable = false) 
    private String diretoria; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "sigla_diretoria", insertable = false, updatable = false) 
    private String siglaDiretoria; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "sala", insertable = false, updatable = false) 
    private String sala; 

    @Field(store = Store.NO, index = Index.YES, analyze = Analyze.YES) 
    @Column(name = "predio", insertable = false, updatable = false) 
    private String predio; 

    //... getters and setters ommited 

    @Override 
    public String toString() { 
    return "Colaborador [id=" + id + ", matricula=" + matricula + ", nome=" + nome + ", email=" + email + ", foto=" + foto + ", login=" + login + ", ramal=" + ramal + ", ua=" 
     + ua + ", situacaoId=" + situacaoId + ", situacao=" + situacao + ", vinculoId=" + vinculoId + ", vinculo=" + vinculo + ", diretoria=" + diretoria 
     + ", siglaDiretoria=" + siglaDiretoria + ", sala=" + sala + ", predio=" + predio + "]"; 
    } 
} 

И мой DAO, где искать с Hibernate Search ...

ColaboradorDAO (управляемый Spring)

import java.util.List; 

import javax.persistence.TypedQuery; 

import org.apache.log4j.LogManager; 
import org.apache.log4j.Logger; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.Sort; 
import org.apache.lucene.search.SortField; 
import org.hibernate.search.jpa.FullTextEntityManager; 
import org.hibernate.search.jpa.FullTextQuery; 
import org.hibernate.search.jpa.Search; 
import org.hibernate.search.query.dsl.QueryBuilder; 
import org.springframework.stereotype.Repository; 

@Repository("colaboradorDAO") 
public class ColaboradorDAO extends AbstractDAO<Colaborador, Long> { 

    private static final Logger logger = LogManager.getLogger(ColaboradorDAO.class); 

    @SuppressWarnings("unchecked") 
    public List<Colaborador> filtrar(Object termo) throws DAOException { 
    try { 
     FullTextEntityManager fullTextEm = Search.getFullTextEntityManager(this.entityManager); 
     QueryBuilder qb = fullTextEm.getSearchFactory().buildQueryBuilder().forEntity(Colaborador.class).get(); 

     Query query = qb.keyword() 
      .onFields("matricula", "nome", "email", "login", "ramal", "ua", "diretoria", "siglaDiretoria", "sala", "predio") 
      .matching(termo) 
      .createQuery(); 

     FullTextQuery fullTextQuery = fullTextEm.createFullTextQuery(query); 
     Sort sortField = new Sort(new SortField("nome", SortField.STRING)); 
     fullTextQuery.setSort(sortField); 
     return fullTextQuery.getResultList(); 
    } 
    catch (Exception e) { 
     logger.error("Erro ao filtrar colaboradores com termo: " + termo, e); 
     throw new DAOException(e); 
    } 
    } 

    public void indexar() throws DAOException { 
     FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager); 

     try { 
      fullTextEntityManager.createIndexer().startAndWait(); 
     } 
     catch (InterruptedException e) { 
      logger.error("Erro ao criar indice de busca dos colaboradores", e); 
      throw new DAOException(e); 
     } 
    } 
} 

Когда я называю filtrar(String termo) метод , он работает как шарм без ошибок и исключений. Но когда я результат запроса является только одной записью, создается объект Colaborador, но все элементы - null.

Пример:

@Test 
public void testColaborador() { 
    try { 
     List<Colaborador> listColaborador = this.colaboradorService.filtrar("060091"); 
     for (Colaborador c : listColaborador) { 
      System.out.println(c.getNome()); 
     } 
    } 
    catch (ServiceException e) { 
     e.printStackTrace(); 
    } 
} 

Результат:

null 

Если изменить строку: System.out.println(c.getNome()); к System.out.println(c.toString()); тогда, отлично подходит для печати всех элементов работает.

Я использую:

  • Hibernate Search 4.3.0.Final;
  • Hibernate Core 4.2.2.Final;
  • Весна 3.2.3.RELEASE;
  • Lucene 3.6.2;

Обновление моего вопроса:

Я модернизированная Hibernate Search версию для 4.4.0.Alpha1 и ошибка по-прежнему сохраняется. Я также понял, что мое лицо связано с «ленивой нагрузкой». Когда я проверяю свою сущность, все свойства имеют значение null, но есть другое свойство, называемое JavassistLazyInitializer.

ответ

2

Ну, проблема решена! Я не могу использовать ключевое слово final для методов getters и seters на сущности. Когда я аннотированный методы получения вместо этого private полей, как сказал @Sanne, это сообщение об ошибке показывает на консоли:

ERROR PojoEntityTuplizer:201 - HHH000112: Getters of lazy classes cannot be final 

Затем я удалил все конечные ключевые слова моего лица Colaborador и работает! Итак, я изменил аннотации на частных полях, и он все еще работает!

Спасибо!

0

ли вам код не только означает, что c.getNome() является нуль? Вы проверили свои данные? Это так? Учитывая, что c.toString() работает, вы наверняка получаете обратно объект. Или вы говорите, что в представлении toString есть значение для nome?

+0

Метод 'c.getNome()' и все другие методы get возвращают 'null'. Для меня это странная ошибка, потому что метод 'toString()' правильно заполнен правильными данными. Как я уже сказал, это происходит только тогда, когда возвращается одна запись. Спасибо за ваш ответ! –

+1

Поиск использует другую стратегию, когда нужно инициализировать только один объект, что действительно может вызвать некоторую странность в прокси-серверах Javassist. Не могли бы вы попытаться аннотировать геттеры вместо частных полей? – Sanne

+0

@ Санне, большое вам спасибо! Ну, ваш ответ почти прав. Действительно, это не расположение аннотаций, а ключевое слово 'final' на' getters' и 'seters'! Я такой тупой! Я удалил все ключевое слово 'final' и получил! Работает как шарм! Благодаря! –

Смежные вопросы