3

Hibernate Search / Lucene returns null elements when the result is a record

 2 years ago
source link: https://www.codesd.com/item/hibernate-search-lucene-returns-null-elements-when-the-result-is-a-record.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Hibernate Search / Lucene returns null elements when the result is a record

advertisements

I am facing a strange issue here with Hibernate Search and Lucene. I believe this problem is kinda simple: when I'm searching something that returns more than one record, everything works fine. When I'm searching something that return only one record, then the entity elements are all null, but when I call the toString() method, everything is there.

My 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 + "]";
    }
}

And my DAO, where I search with Hibernate Search...

ColaboradorDAO (managed by 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);
        }
    }
}

When I call the filtrar(String termo) method, it works like a charm with no errors and no exceptions. But when I the result of the query is only one record, then the Colaborador entity is instantiated but all elements are null.

Example:

@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();
    }
}

Result:

null

If I change the line: System.out.println(c.getNome()); to System.out.println(c.toString()); then, works great for printing out all elements.

I am using:

  • Hibernate Search 4.3.0.Final;
  • Hibernate Core 4.2.2.Final;
  • Spring 3.2.3.RELEASE;
  • Lucene 3.6.2;

Updating my question:

I've upgraded Hibernate Search version to 4.4.0.Alpha1 and the error still persist. I also realized that my entity is related with "lazy load". When I inspect my entity, all properties are null, but there is another property called JavassistLazyInitializer.


Well, problem solved! I can't use the final keyword for methods getters and setters on the entity. When I annotated the getters instead the private fields, like @Sanne said, this error message shows on console:

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

Then I removed all final keywords of my entity Colaborador and works! So, I changed back the annotations on private fields, and it still working!

Thank you!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK