Нет типа данных для узла с функцией Postgis ST_Distance в построителе критериев

#java #hibernate #postgis #criteria

Вопрос:

Всем привет Я отчаянно пытаюсь выполнить пользовательскую функцию в построителе критериев, чтобы получить ближайший город из точки, используя функцию Postgis ST_Distance, но, похоже, она не читает функцию, так как она возвращает мне эту ошибку:

 java.lang.IllegalArgumentException: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode   -[METHOD_CALL] MethodNode: 'function (ST_Distance)'   -[METHOD_NAME] IdentNode: 'ST_Distance' {originalText=ST_Distance}  -[EXPR_LIST] SqlNode: 'exprList'   -[DOT] DotNode: 'commune1_.geometrie' {propertyName=geometrie,dereferenceType=PRIMITIVE,getPropertyPath=geometrie,path=generatedAlias1.geometrie,tableAlias=commune1_,className=com.gu.domain.model.Commune,classAlias=generatedAlias1}  |  -[ALIAS_REF] IdentNode: 'commune1_.idcommune' {alias=generatedAlias1, className=com.gu.domain.model.Commune, tableAlias=commune1_}  | -[IDENT] IdentNode: 'geometrie' {originalText=geometrie}   -[METHOD_CALL] MethodNode: 'function (GeomFromText)'  |  -[METHOD_NAME] IdentNode: 'GeomFromText' {originalText=GeomFromText}  | -[EXPR_LIST] SqlNode: 'exprList'  |  -[NAMED_PARAM] ParameterNode: '?' {name=param1, expectedType=null}  | -[NUM_INT] LiteralNode: '4326'  -[NAMED_PARAM] ParameterNode: '?' {name=param2, expectedType=null}  [select generatedAlias0 from com.gu.domain.model.Commune as generatedAlias0 where ( ST_Distance(:param0, generatedAlias0.geometrie)=(select function('ST_Distance', generatedAlias1.geometrie, function('GeomFromText', :param1, 4326), :param2) from com.gu.domain.model.Commune as generatedAlias1) ) and ( generatedAlias0.dateModifgt;=:param3 )]  

Я думаю, что, возможно, Postgis или что-то еще не позволяет понять команду ST_Distance, но как я могу сделать это лучше ?

Моя пользовательская функция PostGISQueryBuilder для вычисления расстояния, которая возвращает двойное значение.

  public class PostGISQueryBuilder implements GisQueryBuilder {  private static final Logger logger = LoggerFactory.getLogger(PostGISQueryBuilder.class);   public static final int WGS84_SRID = 4326;  private static final String BBOX_FUNCTION = "BOX3D";  private static final String DISTANCE_SPHERE_FUNCTION = "distance_sphere";  private static final String DISTANCE_FUNCTION = "distance_sphere";  private static final String GEOM_FROM_TEXT_FUNCTION = "GeomFromText";  private static final String OVERLAPS_FUNCTION = "amp;amp;";  private static final String OVERLAPS_FUNCTION_OGC = "overlaps"; // for JPA..  private static final String POINT = "POINT";  private static final double RADIUS_OF_EARTH_IN_METERS = 6371008;   public Expressionlt;Doublegt; distanceSpheroidExpression(CriteriaBuilder criteriaBuilder,  Expressionlt;Geometrygt; locationExpression,  Point centroid) {  return criteriaBuilder.function(  "ST_Distance",  Double.class,  locationExpression,  criteriaBuilder.function(  GEOM_FROM_TEXT_FUNCTION,  Geometry.class,  criteriaBuilder.literal(new WKTWriter(2).write(centroid)),  criteriaBuilder.literal(WGS84_SRID)),  criteriaBuilder.literal(true));   } }  

GisQueryBuilder, который расширяет PostGisQueryBuilder

 public interface GisQueryBuilder {  Expressionlt;Doublegt; distanceSpheroidExpression(CriteriaBuilder criteriaBuilder,  Expressionlt;Geometrygt; locationExpression,  Point centroid);   Predicate withinPredicate(CriteriaBuilder criteriaBuilder,  Expressionlt;Geometrygt; locationExpression,  Point centroid,  Double numericDistanceInMeters);  }    

The criteria Builder

 @Override  public Commune getClosestCommune(Geometry geometrie) {   CriteriaBuilder cb = getCriteriaBuilder();  CriteriaQuerylt;Communegt; cq = cb.createQuery(Commune.class);  Rootlt;Communegt; commune = cq.from(Commune.class);    Subquerylt;Doublegt; minDistance = cq.subquery(Double.class);  Rootlt;Communegt; rootCommuneSubquery = minDistance.from(Commune.class);   Point pointGeometry = geometrie.getCentroid();     DistancePredicate distance = new DistancePredicate((CriteriaBuilderImpl) cb, geometrie ,commune.get(Commune_.geometrie), null);     PostGISQueryBuilder postgis = new PostGISQueryBuilder();  minDistance.select(postgis.distanceSpheroidExpression((CriteriaBuilderImpl) cb, rootCommuneSubquery.get(Commune_.geometrie), pointGeometry));    cq.select(commune).where(cb.and(cb.equal(distance, minDistance)),  cb.greaterThanOrEqualTo(commune.get(Commune_.dateModif), dateReference));    return getSingleResult(cq);