Search code examples
hibernate-search

How to implement a @FieldBridge to an @EmbeddedId field


When there is an @EmbeddedId field, a custom Field Bridge should be implemented. There is a Feature opened about it https://hibernate.atlassian.net/browse/HSEARCH-1879. But it isn't ready yet.

In this case, the interface correct to implement is TwoWayFieldBridge?

Below is my implementation for a composite ID with 5 fields.

public class ChavePrimariaAcompanhamentoBridge implements TwoWayFieldBridge {

    @Override
    public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {

        AcompanhamentoPK chavePrimaria = (AcompanhamentoPK) value;

        Integer ano = chavePrimaria.getAno();
        Integer mes = chavePrimaria.getMes();
        Long codigoCredenciada = chavePrimaria.getCredenciada().getCodigo();
        Long codigoPosto = chavePrimaria.getPostoAtendimento().getCodigo();
        Integer numeroSequencial = chavePrimaria.getNumeroSequencial();

        luceneOptions.addNumericFieldToDocument("mes", mes, document);
        luceneOptions.addNumericFieldToDocument("ano", ano, document);
        luceneOptions.addNumericFieldToDocument("credenciada.codigo", codigoCredenciada, document);
        luceneOptions.addNumericFieldToDocument("postoAtendimento.codigo", codigoPosto, document);
        luceneOptions.addNumericFieldToDocument("numeroSequencial", numeroSequencial, document);
    }

    @Override
    public Object get(String name, Document document) {

        AcompanhamentoPK chavePrimaria = new AcompanhamentoPK();
        chavePrimaria.setMes(Integer.valueOf(document.get("mes")));
        chavePrimaria.setAno(Integer.valueOf(document.get("ano")));
        chavePrimaria.setCredenciada(new Credenciada(Long.valueOf(document.get("credenciada.codigo"))));
        chavePrimaria.setPostoAtendimento(new CadastroPostoAtendimento(Long.valueOf(document.get("postoAtendimento.codigo"))));
        chavePrimaria.setNumeroSequencial(Integer.valueOf(document.get("numeroSequencial")));

        return chavePrimaria;
    }

    @Override
    public String objectToString(Object value) {
        AcompanhamentoPK chavePrimaria = (AcompanhamentoPK) value;

        return chavePrimaria.toString();
    }

}

1 - Is there another best way to make it?

2 - Is there any error(about concepts) in this implementation?

3 - What is the objectToString method used for? It is important?

I am making this question because I haven't found any documentation about it, so I am not sure.


Solution

  • EDIT: In Hibernate Search 6+, in order to map an @EmbeddedId, you should use a custom IdentifierBridge: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#mapper-orm-bridge-identifierbridge


    Original answer for Hibernate Search 5:

    In this case, the interface correct to implement is TwoWayFieldBridge?

    Yes: https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#_two_way_bridge

    1 - Is there another best way to make it?

    Not that I know of.

    2 - Is there any error(about concepts) in this implementation?

    Yes.

    • You shouldn't use Integer.valueOf here. Just call Field.numericValue() on the result of document.get, and cast the result to Integer.

    • You should also store the unique string representation of the ID in the set() method:

       luceneOptions.addFieldToDocument( name, objectToString( id ), document );
      

    3 - What is the objectToString method used for?

    Hibernate Search will use the result of this method mostly to build queries, for example when it must retrieve documents that should be deleted, or when you query the ID field explicitly.

    It is important?

    Nothing will work unless you implement it properly, i.e. unless you make sure that:

    • it returns two different values for two different composite IDs
    • it always returns the same value for a given composite ID