是否可以使用jpa CriteriaBuilder在 column_list 上调用Microsoft SQL Server的FREETEXT函数?
可以在单个列或列列表上本机调用SQL Server的FREETEXT函数: https://docs.microsoft.com/en-us/sql/t-sql/queries/freetext-transact-sql
我发现这个后可以在一个列上调用FREETEXT: https://stackoverflow.com/a/18534291/6659983
当我尝试在多个列上调用FREETEXT时,在调用FREETEXT时,我无法找到一种方法来让hibernate在 column_list 周围添加括号。
我覆盖ParamaterizedFunctionExpression.renderArguments()
并最终设法获得生成的HQL(或某种中间类型的QL),如下所示:
select
generatedAlias0
from
package.model.entity as generatedAlias0
inner join generatedAlias0.categories as generatedAlias1
inner join generatedAlias1.unspsc as generatedAlias2
inner join generatedAlias0.buyer as generatedAlias3
inner join generatedAlias0.otherEntity as generatedAlias4
where
( function('FREETEXT', ( generatedAlias0.title, generatedAlias0.description, generatedAlias0.code, generatedAlias3.name, generatedAlias3.legalName, generatedAlias2.title ) , :param0) ) and ( generatedAlias0.state=:param1 )
and ( generatedAlias0.state<>:param2 )
and ( generatedAlias0.state<>:param3 )
and ( generatedAlias0.state<>:param4 )
order by
generatedAlias0.closingDate asc]
我收到了这个错误:
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: function (FREETEXT) near line 1, column 319 [select generatedAlias0 from package.model.Entity as generatedAlias0 inner join generatedAlias0.categories as generatedAlias1 inner join generatedAlias1.unspsc as generatedAlias2 inner join generatedAlias0.buyer as generatedAlias3 inner join generatedAlias0.entityBoxes as generatedAlias4 where ( function('FREETEXT', ( generatedAlias0.title, generatedAlias0.description, generatedAlias0.code, generatedAlias3.name, generatedAlias3.legalName, generatedAlias2.title ) , :param0) ) and ( generatedAlias0.state=:param1 ) and ( generatedAlias0.state<>:param2 ) and ( generatedAlias0.state<>:param3 ) and ( generatedAlias0.state<>:param4 ) order by generatedAlias0.closingDate asc]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:131)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:663)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3318)
at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:318)
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3611)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
at package.entity.dao.EntityDaoImpl.search(EntityDaoImpl.java:241)
这是我努力扩展ParameterizedFunctionExpression:
/**
* Overrides the {@link ParameterizedFunctionExpression.renderArguments()} function
* so that the FREETEXT search can be created properly.
*/
private class FreeTextExpression extends ParameterizedFunctionExpression<Boolean> implements Predicate {
/**
* Eclipse Generated UID.
*/
private static final long serialVersionUID = -1219262363097942038L;
private List<Expression<?>> argumentExpressions;
/**
* Constructs a 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 all arguments except the first within brackets in order to define a MSSQL 'column_list'.
*/
@Override
protected void renderArguments(StringBuilder buffer, RenderingContext renderingContext) {
String sep = "";
buffer.append(" ( ");
for (int i = 0; i < argumentExpressions.size() - 1 ; i ++) {
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;
}
}
以下是我如何使用它:
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);
答案 0 :(得分:0)
哎呀,我意识到我需要注册这样的函数,但对于FREETEXT:
registerFunction("CONTAINS", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "CONTAINS(?1, ?2) AND 1"));
Hibernate + MSSQL + Fulltext Search via Contains SQLFunctionTemplate
一旦我完成了它就会发布代码,除非有人能打败我!
答案 1 :(得分:-1)
请试试这个:
select
generatedAlias0
from
package.model.entity as generatedAlias0
inner join generatedAlias0.categories as generatedAlias1
inner join generatedAlias1.unspsc as generatedAlias2
inner join generatedAlias0.buyer as generatedAlias3
inner join generatedAlias0.otherEntity as generatedAlias4
where
FREETEXT( generatedAlias0,@param0) ) and ( generatedAlias0,@param1 )
and ( generatedAlias0.state<>:param2 )
and ( generatedAlias0.state<>:param3 )
and ( generatedAlias0.state<>:param4 )
order by
generatedAlias0.closingDate asc]