У меня возникает странная проблема с 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
.
Метод 'c.getNome()' и все другие методы get возвращают 'null'. Для меня это странная ошибка, потому что метод 'toString()' правильно заполнен правильными данными. Как я уже сказал, это происходит только тогда, когда возвращается одна запись. Спасибо за ваш ответ! –
Поиск использует другую стратегию, когда нужно инициализировать только один объект, что действительно может вызвать некоторую странность в прокси-серверах Javassist. Не могли бы вы попытаться аннотировать геттеры вместо частных полей? – Sanne
@ Санне, большое вам спасибо! Ну, ваш ответ почти прав. Действительно, это не расположение аннотаций, а ключевое слово 'final' на' getters' и 'seters'! Я такой тупой! Я удалил все ключевое слово 'final' и получил! Работает как шарм! Благодаря! –