sql server - FREETEXT search on a 'column_list' using hibernate CriteriaBuilder -


is possible call microsoft sql server's freetext function on column_list using jpa criteriabuilder?

the sql server's freetext function can called natively on either single column, or list of columns: https://docs.microsoft.com/en-us/sql/t-sql/queries/freetext-transact-sql

i can call freetext on single column after finding this: https://stackoverflow.com/a/18534291/6659983

when try call freetext on multiple columns, can't find way hibernate put brackets around column_list when call freetext.

i overrode paramaterizedfunctionexpression.renderarguments() , managed generated hql (or intermediate sort of ql) looked this:

select      generatedalias0       package.model.entity generatedalias0      inner join generatedalias0.categories generatedalias1      inner join generatedalias1.unspsc generatedalias2      inner join generatedalias0.buyer generatedalias3      inner join generatedalias0.otherentity generatedalias4       ( function('freetext',  ( generatedalias0.title, generatedalias0.description, generatedalias0.code, generatedalias3.name, generatedalias3.legalname, generatedalias2.title ) , :param0) ) , ( generatedalias0.state=:param1 )      , ( generatedalias0.state<>:param2 )      , ( generatedalias0.state<>:param3 )      , ( generatedalias0.state<>:param4 )  order      generatedalias0.closingdate asc] 

and got error:

    java.lang.illegalargumentexception: org.hibernate.hql.internal.ast.querysyntaxexception: unexpected ast node: function (freetext) near line 1, column 319 [select generatedalias0 package.model.entity generatedalias0 inner join generatedalias0.categories generatedalias1 inner join generatedalias1.unspsc generatedalias2 inner join generatedalias0.buyer generatedalias3 inner join generatedalias0.entityboxes generatedalias4 ( function('freetext', ( generatedalias0.title, generatedalias0.description, generatedalias0.code, generatedalias3.name, generatedalias3.legalname, generatedalias2.title ) , :param0) ) , ( generatedalias0.state=:param1 ) , ( generatedalias0.state<>:param2 ) , ( generatedalias0.state<>:param3 ) , ( generatedalias0.state<>:param4 ) order generatedalias0.closingdate asc]         @ org.hibernate.internal.exceptionconverterimpl.convert(exceptionconverterimpl.java:131)         @ org.hibernate.internal.exceptionconverterimpl.convert(exceptionconverterimpl.java:155)         @ org.hibernate.internal.exceptionconverterimpl.convert(exceptionconverterimpl.java:162)         @ org.hibernate.internal.abstractsharedsessioncontract.createquery(abstractsharedsessioncontract.java:663)         @ org.hibernate.internal.sessionimpl.createquery(sessionimpl.java:3318)         @ org.hibernate.query.criteria.internal.criteriaqueryimpl$1.buildcompiledquery(criteriaqueryimpl.java:318)         @ org.hibernate.query.criteria.internal.compile.criteriacompiler.compile(criteriacompiler.java:127)         @ org.hibernate.internal.sessionimpl.createquery(sessionimpl.java:3611)         @ org.hibernate.internal.sessionimpl.createquery(sessionimpl.java:203)         @ package.entity.dao.entitydaoimpl.search(entitydaoimpl.java:241) 

here effort extend parameterizedfunctionexpression:

/**      * overrides {@link parameterizedfunctionexpression.renderarguments()} function      * freetext search can created properly.      */     private class freetextexpression extends parameterizedfunctionexpression<boolean> implements predicate {          /**          * eclipse generated uid.          */         private static final long serialversionuid = -1219262363097942038l;          private list<expression<?>> argumentexpressions;          /**          * constructs freetextexpression          * @param criteriabuilder          * @param returntype          * @param functionname          * @param argumentexpressions          */         public freetextexpression(                 criteriabuilderimpl criteriabuilder,                 string functionname,                 list<expression<?>> argumentexpressions) {             super( criteriabuilder, (class<boolean>) boolean.class , functionname , argumentexpressions);             this.argumentexpressions = argumentexpressions;         }          /**          * places arguments except first within brackets in order define mssql 'column_list'.          */         @override         protected void renderarguments(stringbuilder buffer, renderingcontext renderingcontext) {             string sep = "";             buffer.append(" ( ");             (int = 0; < argumentexpressions.size() - 1 ; ++) {                 buffer.append( sep ).append( ( (renderable) argumentexpressions.get(i) ).render( renderingcontext ) );                 sep = ", ";             }             buffer.append(" ) ");             buffer.append( sep ).append( ( (renderable) argumentexpressions.get(argumentexpressions.size() - 1) ).render( renderingcontext ) );         }          @override         public booleanoperator getoperator() {             return predicate.booleanoperator.and;         }          @override         public boolean isnegated() {             return false;         }          @override         public list<expression<boolean>> getexpressions() {             return arrays.aslist(this);         }          @override         public predicate not() {             return null;         }     } 

here how use it:

    list<expression<?>> arguments = arrays.aslist(                     entity.<string>get(entity_.title),                     entity.<string>get(entity_.description),                     entity.<string>get(entity_.code),                     buyer.<string>get(business_.name),                     buyer.<string>get(business_.legalname),                     unspsc.<string>get(unspsc_.title),                     (expression<string>) keywords             );              expression<boolean> freetextexpression = new freetextexpression(                     (criteriabuilderimpl) builder, "freetext", arguments);             criteria.add((predicate) freetextexpression); 

oops, realised need register function this, freetext:

registerfunction("contains", new sqlfunctiontemplate(standardbasictypes.boolean, "contains(?1, ?2) , 1")); 

hibernate + mssql + fulltext search via contains sqlfunctiontemplate

will post code once i've worked out, unless can beat me it!


Comments

Post a Comment