Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: TwoWayStringBridge on a CSV Field for Hibernate Search 5.5.2
PostPosted: Thu Mar 10, 2016 12:35 am 
Newbie

Joined: Sun Feb 21, 2016 3:15 pm
Posts: 5
hi, back again - i have been facing this issue again since the past 3 days - i have tried all ways - but the field conversion does not happen!

the requirement is that i have a csv field in my database of the type keywords that needs to be accessed and indexed as a keyword string each.
like clothes, clothing, fabric may be stored in the database in a single column - but they need to be accessed and indexed as each term that is 'clothes' | 'clothing' | 'fabric' are all separate.
hence, i am using list<string> as advised in some forums along with a twowaystringbridge to convert from csv-string to list and from list to csv-string.

Code:
   @Column(name="dhl_cs_product_keywords", nullable=false, length=1000)
   @Field(index=Index.YES, analyze=Analyze.YES, store=Store.NO, bridge=@FieldBridge(impl=DHLCSKeywordFieldBridge.class))
     // is it a bird, is it a plane - it is fieldbridge! - solution for csv fields in hibernate search/lucene
    public List<String> getDhlCsItemKeywords() {
        return this.dhlCsItemKeywords;
    }


and this is the implementation of the field bridge
Code:

public class DHLCSKeywordFieldBridge implements TwoWayStringBridge {

   public String objectToString(Object value)
   {
      if ( value == null ) {
         return null;
      }
            
      // set is mandatory
      if ( !( value instanceof Collection ) ) {
         throw new IllegalArgumentException( "This FieldBridge only supports Collections (List)." );
      }
      
      List<String> objects = (List <String>) value;   
      
      StringBuffer buf = new StringBuffer();
      if (value != null) {
      
         Collection<?> col = (Collection<?>) value;
         Iterator<?> it = col.iterator();
         
         // convert to csv
         while (it.hasNext()) {
            String next = it.next().toString();
            buf.append(next);
            if (it.hasNext())
               buf.append(", ");
         }
      }
   
      // simply a string representation
      return buf.toString();
   }

   public List<String> stringToObject(String arg0) {

      List<String> keywords = new ArrayList<String>();
      
      // string to list - no null checks or bounds
      StringTokenizer sTokenizer = new StringTokenizer(arg0, ",");
      while(sTokenizer.hasMoreTokens()) {
         keywords.add(sTokenizer.nextToken());
      }
      return keywords;
   }
}



is this the right usage of a two way string bridge? i am getting the following error on simply hibernate initialization inside weblogic 12c.
Code:
org.hibernate.MappingException: Could not determine type for: java.util.List, at table: dhl_cs_classification, for columns: [org.hibernate.mapping.Column(dhl_cs_product_keywords)]
        at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:396)
        at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:369)
        at org.hibernate.mapping.Property.isValid(Property.java:225)
        at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:529)
        at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
        at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:443)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
        at com.aptean.dhl.cs.persistence.configuration.DHLCSPersistenceConfiguration.<clinit>(DHLCSPersistenceConfiguration.java:34)
        at com.aptean.dhl.cs.search.impl.DHLCSSearchImpl.<clinit>(DHLCSSearchImpl.java:49)
        at com.aptean.dhl.cs.service.impl.DHLCSServiceImpl.getAllKeywords(DHLCSServiceImpl.java:65)
        at com.aptean.dhl.cs.ws.DHLCSWebServiceImpl.getAllKeywords(DHLCSWebServiceImpl.java:78)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
        at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
        at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(AbstractJAXWSMethodInvoker.java:178)
        at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:68)
        at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
        at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
        at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:107)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
        at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:355)
        at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:319)
        at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1074)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1010)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)


Top
 Profile  
 
 Post subject: Re: TwoWayStringBridge on a CSV Field for Hibernate Search 5.5.2
PostPosted: Tue Mar 29, 2016 4:38 am 
Hibernate Team
Hibernate Team

Joined: Sat Jan 24, 2009 12:46 pm
Posts: 386
The error you see is a mapping error from Hibernate ORM, you first need to properly map the List<String> by terms of JPA. Add @ElementCollection for that purpose (which will cause creating of a mapping table for storing all the keywords of an entity).

Regarding field bridges, check out section 4.4.3.2 in the reference guide: https://docs.jboss.org/hibernate/search ... om-bridges. Your implementation could roughly look like so:

Code:
public class KeywordListFieldBridge implements FieldBridge {

    public void set(String name, Object value, Document document,
                    LuceneOptions luceneOptions) {
        List<String> keywords = (List<String>) value;

        for(String keyword : keywords) {
            luceneOptions.addFieldToDocument(name, keyword, document);
        }
    }
}


This bridge will add a multi-valued field with name <name> to the index, with one element per keyword contained in the list.

--Gunnar

_________________
Visit my blog at http://musingsofaprogrammingaddict.blogspot.com/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.