添加Hibernate Search

时间:2015-11-18 12:34:23

标签: java hibernate hibernate-search hibernate-spatial

我正在开发一个项目,我正在使用Hibernate 5,它运行良好。现在,我要完成的是集成Hibernate Search,以便我可以通过它们的一些String类型属性来查找对象。顺便说一句,我是Hibernate Search的新手。

好消息是这个项目非常简单,因为只包含两个类:ParadaWS和OperadorWS。这些是类:

ParadaWS 上课:

    package model.paradasws;

    import java.io.Serializable;

    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    import javax.persistence.Table;
    import javax.persistence.Transient;
    import javax.validation.constraints.NotNull;

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.hibernate.search.annotations.Analyze;
    import org.hibernate.search.annotations.Field;
    import org.hibernate.search.annotations.FieldBridge;
    import org.hibernate.search.annotations.Index;
    import org.hibernate.search.annotations.Indexed;
    import org.hibernate.search.annotations.Store;

    import com.vividsolutions.jts.geom.Point;

    @Entity
    @Table(name = "paradas_ws")
    public class ParadaWS implements Serializable {

        private static final long serialVersionUID = 7772269835230124538L;
        @Transient
        private Logger logger = LogManager.getLogger(ParadaWS.class);

        @Id
        @NotNull
        @Column(name = "codigo_parada")
        private Integer codigoParada;
        @NotNull
        @Column(name = "descripcion_corta")
        private String descripcionCorta;
        @NotNull
        @Column(name = "descripcion_larga")
        private String descripcionLarga;
        @NotNull
        @Column(name = "codigo_municipio")
        private Integer codigoMunicipio;
        @NotNull
        @Column(name = "utmx")
        private Long utmX;
        @NotNull
        @Column(name = "utmy")
        private Long utmY;
        @NotNull
        @Column(name="punto")
        private Point punto;
        @Id
        @ManyToOne(cascade = CascadeType.PERSIST)
        @JoinColumn(name = "operador")
        private OperadorWS operador;

        public ParadaWS(){

        }
        public ParadaWS(Integer codigoParada, String descripcionCorta, String descripcionLarga, Integer codigoMunicipio,
                Long utmX, Long utmY, Point punto, OperadorWS operador) {
            this.codigoParada = codigoParada;
            this.descripcionCorta = descripcionCorta;
            this.descripcionLarga = descripcionLarga;
            this.codigoMunicipio = codigoMunicipio;
            this.utmX = utmX;
            this.utmY = utmY;
            this.punto = punto;
            this.operador = operador;
        }
        public Integer getCodigoParada() {
            return codigoParada;
        }
        public void setCodigoParada(Integer codigoParada) {
            this.codigoParada = codigoParada;
        }
        public String getDescripcionCorta() {
            return descripcionCorta;
        }
        public void setDescripcionCorta(String descripcionCorta) {
            this.descripcionCorta = descripcionCorta;
        }
        public String getDescripcionLarga() {
            return descripcionLarga;
        }
        public void setDescripcionLarga(String descripcionLarga) {
            this.descripcionLarga = descripcionLarga;
        }
        public Integer getCodigoMunicipio() {
            return codigoMunicipio;
        }
        public void setCodigoMunicipio(Integer codigoMunicipio) {
            this.codigoMunicipio = codigoMunicipio;
        }
        public Long getUtmX() {
            return utmX;
        }
        public void setUtmX(Long utmX) {
            this.utmX = utmX;
        }
        public Long getUtmY() {
            return utmY;
        }
        public void setUtmY(Long utmY) {
            this.utmY = utmY;
        }
        public Point getPunto() {
            return punto;
        }
        public void setPunto(Point punto) {
            this.punto = punto;
        }
        public OperadorWS getOperador() {
            return operador;
        }
        public void setOperador(OperadorWS operador) {
            this.operador = operador;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((codigoMunicipio == null) ? 0 : codigoMunicipio.hashCode());
            result = prime * result + ((codigoParada == null) ? 0 : codigoParada.hashCode());
            result = prime * result + ((descripcionCorta == null) ? 0 : descripcionCorta.hashCode());
            result = prime * result + ((descripcionLarga == null) ? 0 : descripcionLarga.hashCode());
            result = prime * result + ((operador == null) ? 0 : operador.hashCode());
            result = prime * result + ((punto == null) ? 0 : punto.hashCode());
            result = prime * result + ((utmX == null) ? 0 : utmX.hashCode());
            result = prime * result + ((utmY == null) ? 0 : utmY.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof ParadaWS)) {
                return false;
            }
            ParadaWS other = (ParadaWS) obj;
            if (codigoMunicipio == null) {
                if (other.codigoMunicipio != null) {
                    return false;
                }
            } else if (!codigoMunicipio.equals(other.codigoMunicipio)) {
                return false;
            }
            if (codigoParada == null) {
                if (other.codigoParada != null) {
                    return false;
                }
            } else if (!codigoParada.equals(other.codigoParada)) {
                return false;
            }
            if (descripcionCorta == null) {
                if (other.descripcionCorta != null) {
                    return false;
                }
            } else if (!descripcionCorta.equals(other.descripcionCorta)) {
                return false;
            }
            if (descripcionLarga == null) {
                if (other.descripcionLarga != null) {
                    return false;
                }
            } else if (!descripcionLarga.equals(other.descripcionLarga)) {
                return false;
            }
            if (operador == null) {
                if (other.operador != null) {
                    return false;
                }
            } else if (!operador.equals(other.operador)) {
                return false;
            }
            if (punto == null) {
                if (other.punto != null) {
                    return false;
                }
            } else if (!punto.equals(other.punto)) {
                return false;
            }
            if (utmX == null) {
                if (other.utmX != null) {
                    return false;
                }
            } else if (!utmX.equals(other.utmX)) {
                return false;
            }
            if (utmY == null) {
                if (other.utmY != null) {
                    return false;
                }
            } else if (!utmY.equals(other.utmY)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "ParadaWS [codigoParada=" + codigoParada + ", descripcionCorta=" + descripcionCorta
                    + ", descripcionLarga=" + descripcionLarga + ", codigoMunicipio=" + codigoMunicipio + ", utmX=" + utmX
                    + ", utmY=" + utmY + ", punto=" + punto + ", operador=" + operador + "]";
        }

    }

OperadorWS 类:

    package model.paradasws;

    import java.io.Serializable;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    import javax.persistence.Transient;
    import javax.validation.constraints.NotNull;

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.hibernate.search.annotations.Analyze;
    import org.hibernate.search.annotations.Field;
    import org.hibernate.search.annotations.Index;
    import org.hibernate.search.annotations.Store;

    @Entity
    @Table(name = "operadores_ws")
    public class OperadorWS implements Serializable {

        private static final long serialVersionUID = 1L;
        @Transient
        private Logger logger = LogManager.getLogger(OperadorWS.class);

        /*
         Atributos
         */
        @Id
        @NotNull
        @Column(name = "codigo_operador")
        private Integer codigoOperador;
        @NotNull
        @Column(name = "descripcion_corta")
        @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        private String descripcionCorta;
        @NotNull
        @Column(name = "descripcion_larga")
        private String descripcionLarga;
        @NotNull
        @Column(name = "direccion_web")
        private String direccionWeb;
        @NotNull
        @Column(name = "telefono")
        private String telefono;

        /*
         Métodos
         */
        public OperadorWS(){

        }

        public OperadorWS(Logger logger, Integer codigoOperador, String descripcionCorta, String descripcionLarga,
                String direccionWeb, String telefono) {
            this.logger = logger;
            this.codigoOperador = codigoOperador;
            this.descripcionCorta = descripcionCorta;
            this.descripcionLarga = descripcionLarga;
            this.direccionWeb = direccionWeb;
            this.telefono = telefono;
        }

        public Logger getLogger() {
            return logger;
        }

        public void setLogger(Logger logger) {
            this.logger = logger;
        }

        public Integer getCodigoOperador() {
            return codigoOperador;
        }

        public void setCodigoOperador(Integer codigoOperador) {
            this.codigoOperador = codigoOperador;
        }

        public String getDescripcionCorta() {
            return descripcionCorta;
        }

        public void setDescripcionCorta(String descripcionCorta) {
            this.descripcionCorta = descripcionCorta;
        }

        public String getDescripcionLarga() {
            return descripcionLarga;
        }

        public void setDescripcionLarga(String descripcionLarga) {
            this.descripcionLarga = descripcionLarga;
        }

        public String getDireccionWeb() {
            return direccionWeb;
        }

        public void setDireccionWeb(String direccionWeb) {
            this.direccionWeb = direccionWeb;
        }

        public String getTelefono() {
            return telefono;
        }

        public void setTelefono(String telefono) {
            this.telefono = telefono;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((codigoOperador == null) ? 0 : codigoOperador.hashCode());
            result = prime * result + ((descripcionCorta == null) ? 0 : descripcionCorta.hashCode());
            result = prime * result + ((descripcionLarga == null) ? 0 : descripcionLarga.hashCode());
            result = prime * result + ((direccionWeb == null) ? 0 : direccionWeb.hashCode());
            result = prime * result + ((telefono == null) ? 0 : telefono.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof OperadorWS)) {
                return false;
            }
            OperadorWS other = (OperadorWS) obj;
            if (codigoOperador == null) {
                if (other.codigoOperador != null) {
                    return false;
                }
            } else if (!codigoOperador.equals(other.codigoOperador)) {
                return false;
            }
            if (descripcionCorta == null) {
                if (other.descripcionCorta != null) {
                    return false;
                }
            } else if (!descripcionCorta.equals(other.descripcionCorta)) {
                return false;
            }
            if (descripcionLarga == null) {
                if (other.descripcionLarga != null) {
                    return false;
                }
            } else if (!descripcionLarga.equals(other.descripcionLarga)) {
                return false;
            }
            if (direccionWeb == null) {
                if (other.direccionWeb != null) {
                    return false;
                }
            } else if (!direccionWeb.equals(other.direccionWeb)) {
                return false;
            }
            if (telefono == null) {
                if (other.telefono != null) {
                    return false;
                }
            } else if (!telefono.equals(other.telefono)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "OperadorWS [codigoOperador=" + codigoOperador 
                    + ", descripcionCorta=" + descripcionCorta
                    + ", descripcionLarga=" + descripcionLarga 
                    + ", direccionWeb=" + direccionWeb 
                    + ", telefono=" + telefono
                    + "]";
        }

    }

我必须将这两行添加到我的配置中(我以编程方式执行):

cfg.setProperty("hibernate.search.default.directory_provider", "filesystem");
cfg.setProperty("hibernate.search.default.indexBase", "C:/Users/IN006/Desktop/paradas/indexLucene");

所以就是这样,我想添加Hibernate Search支持,使用他们的descripcionCorta和descripcionLarga属性来查找ParadaWS对象。

我该如何配置?我一直在查看官方文档,我需要在ParadaWS类中添加@Indexed注释。然后,需要将@Field注释添加到要将其切换为可搜索的每个属性。这是对的吗?

所以这些将是我对添加Hibernate Search支持的修改:

    @Entity
    @Table(name = "paradas_ws")
    @Indexed
    public class ParadaWS implements Serializable {
        ...
        @NotNull
        @Column(name = "descripcion_corta")
        @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        private String descripcionCorta;
        @NotNull
        @Column(name = "descripcion_larga")
        @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        private String descripcionLarga;
        ...
    }

这够了吗?我可以使用这种方法进行搜索吗?

    public void buscarSimilitudesNombreParada(String pNombreCorto){
        openCurrentSession();
        SearchFactory fact = getHibernateSearch();
        FullTextSession txtSession = getFullTextSession();
        QueryBuilder b = fact.buildQueryBuilder().forEntity(ParadaWS.class).get();

        Query query = b.keyword()
            .fuzzy()
                .withEditDistanceUpTo(1)
                .withPrefixLength(1)
            .onField("descripcionCorta")
            .matching(pNombreCorto)
            .createQuery();

        FullTextQuery txtQuery = txtSession.createFullTextQuery(query, ParadaWS.class);
        List resultados = txtQuery.list();
        for (Object obj : resultados) {
            if(obj instanceof ParadaWS){
                ParadaWS pws = (ParadaWS) obj;
                LogHelper.logDebug(logger, "Una parada tras hibernate search: " + pws.toString(), true);
            }

        }
    }

后来,当我习惯了Hibernate Search时,我想基于Point对象(Spatial features)实现搜索。

感谢您的帮助!

编辑:解决方案 最后,经过几次试验,我想出了解决方案...... ParadaWS课程仍然如下:

    @Entity
    @Table(name = "paradas_ws")
    @Indexed
    public class ParadaWS implements Serializable {
        ...
        @Id
        @NotNull
        @Column(name = "codigo_parada")
        @DocumentId
        private Integer codigoParada;
        @NotNull
        @Column(name = "descripcion_corta")
        @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        private String descripcionCorta;
        @NotNull
        @Column(name = "descripcion_larga")
        @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
        private String descripcionLarga;
        ...
        @Id
        @ManyToOne(cascade = CascadeType.PERSIST)
        @JoinColumn(name = "operador")
        @FieldBridge(impl = OperadorWSBridge.class)
        private OperadorWS operador;
        ...

所以,我有必要建一座桥(我猜这是必须的,因为我有一个复合ID),所以这是我的OperadorWSBridge类:

    package model.paradasws;

    import org.hibernate.search.bridge.TwoWayStringBridge;

    public class OperadorWSBridge implements TwoWayStringBridge {

        @Override
        public String objectToString(Object pObject) {
            return ((OperadorWS) pObject).toString();
        }

        @Override
        public OperadorWS stringToObject(String pStringValue) {
            return OperadorWS.buildFromString(pStringValue);
        }

    }

这是OperadorWS的buildFromString方法(它的作用是解析使用toString()默认方法生成的String,所以我发布了两个):

    public static OperadorWS buildFromString(String pOperadorStr){
        String out = pOperadorStr;
        out = out.replace("OperadorWS [codigoOperador=", "");
        out = out.replace(", descripcionCorta=", ";");
        out = out.replace(", descripcionLarga=", ";");
        out = out.replace(", direccionWeb=", ";");
        out = out.replace(", telefono=", ";");
        out = out.replace("]", "");

        String[] strOut = out.split(";");

        OperadorWS act = new OperadorWS();
        act.setCodigoOperador(Integer.parseInt(strOut[0]));
        act.setDescripcionCorta(strOut[1]);
        act.setDescripcionLarga(strOut[2]);
        act.setDireccionWeb(strOut[3]);
        act.setTelefono(strOut[4]);

        return act;
    }

    @Override
    public String toString() {
        return "OperadorWS [codigoOperador=" + codigoOperador 
                + ", descripcionCorta=" + descripcionCorta
                + ", descripcionLarga=" + descripcionLarga 
                + ", direccionWeb=" + direccionWeb 
                + ", telefono=" + telefono
                + "]";
    }

但是,经过所有这些修改后,我仍然无法使用Hibernate Search 获取数据......你知道为什么吗?我的数据是通过另一个应用程序(每天运行)生成的,因此不是INDEXED 。这是一个很大的缺点,但必须索引所有数据:

public void indexarParadas(){
    openCurrentSession();
    getHibernateSearch();
    FullTextSession txtSession = getFullTextSession();
    txtSession.getTransaction().begin();
    @SuppressWarnings("unchecked")
    List<ParadaWS> paradas = txtSession.createQuery("from ParadaWS").list();
    for (ParadaWS paradaWS : paradas) {
        txtSession.index(paradaWS);
    }
    txtSession.getTransaction().commit();
}

毕竟,我已经能够让Hibernate Search工作了。

0 个答案:

没有答案
相关问题