当结果是一条记录时,Hibernate Search / Lucene返回null元素

时间:2013-08-30 18:54:58

标签: java spring hibernate lucene hibernate-search

我在Hibernate Search和Lucene面临一个奇怪的问题。我相信这个问题有点简单:当我搜索返回多条记录的东西时,一切正常。当我搜索只返回一条记录的东西时,实体元素都是空的,但当我调用toString()方法时,一切都在那里。

我的实体:

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;
  • Spring 3.2.3.RELEASE;
  • Lucene 3.6.2;

更新我的问题:

我已将Hibernate Search版本升级到4.4.0.Alpha1,错误仍然存​​在。我也意识到我的实体与“懒惰负载”有关。当我检查我的实体时,所有属性都为null,但还有另一个名为JavassistLazyInitializer的属性。

2 个答案:

答案 0 :(得分:2)

嗯,问题解决了!我不能将final关键字用于实体上的方法getter和setter。当我注释getter而不是private字段时,就像@Sanne所说,这个错误信息显示在控制台上:

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

然后我删除了我的实体Colaborador的所有最终关键字并且有效!所以,我改回了私有字段上的注释,它仍然有效!

谢谢!

答案 1 :(得分:0)

您的代码不只是暗示 c.getNome() null 吗?你检查过你的数据了吗?是这样的吗?鉴于c.toString()有效,你可以确定一个实体。或者你是说在 toString 表示中有 nome 的值?