2016-09-12 12 views
0

Hibernate-Spatialで述語を使用してXマイル(ユーザ定義)の範囲内で検索しようとしています。Hibernate-Spatial + PostGISの述語を半径の範囲内で緯度/経度で検索する場合

この種の質問は以前に尋ねられていますが、Predicatesを使用する前に一度だけ質問されましたが、動作しないため最新ではない可能性があります。そして、私は述語を使用することができなければならず、HQLは使用できません。

PostGISのWITHINキーワードのためにPredicateをセットアップする方法はありますが、実行するクエリを取得できませんでした。

最後にセットアップした後、エラー出力とパッケージのバージョンを記載します。私のモデルでは

CREATE EXTENSION Postgis; 

CREATE TABLE "user" (
    id    bigint NOT NULL, 
    search_radius int, 
    latitude   double precision, 
    longitude  double precision, 
    location   geography(point, 4326), 

    PRIMARY KEY (id) 
); 

:ここ

は、私は私のスキーマ内に持っているものである

更新場所は緯度/経度のセッター内部で呼び出され
import com.vividsolutions.jts.geom.Point; 
import com.vividsolutions.jts.io.ParseException; 
import com.vividsolutions.jts.io.WKTReader; 
import org.hibernate.annotations.Type; 

@Entity 
@Table(name = "`user`") 
public class User implements UserDetails { 
    @Id 
    private Long id; 
    private Integer searchRadius = 125; 
    private Double latitude; 
    private Double longitude; 
    @Column(name = "location", columnDefinition = "geography(Point, 4326)", nullable = true) 
    @Type(type = "jts_geometry") 
    private Point location; 

    ... 

    private void updateLocation() { 
     if (latitude != null && longitude != null) { 
      try { 
       location = (Point) new WKTReader().read("POINT(" + latitude + " " + longitude + ")"); 
       location.setSRID(Location.SRID); 
      } catch (ParseException e) { 
       e.printStackTrace(); 
       throw new RuntimeException(e); 
      } 
     } 
    } 
} 

私はWithinPredicateと円の工場を使用して、Using JPA Criteria Api and hibernate spatial 4 together

import com.vividsolutions.jts.geom.Geometry; 
import com.vividsolutions.jts.geom.Point; 
import java.io.Serializable; 
import javax.persistence.criteria.Expression; 
import org.hibernate.jpa.criteria.CriteriaBuilderImpl; 
import org.hibernate.jpa.criteria.ParameterRegistry; 
import org.hibernate.jpa.criteria.Renderable; 
import org.hibernate.jpa.criteria.compile.RenderingContext; 
import org.hibernate.jpa.criteria.predicate.AbstractSimplePredicate; 

public class WithinPredicate extends AbstractSimplePredicate implements Expression<Boolean>, Serializable { 
    private final Expression<Point> matchExpression; 
    private final Expression<Geometry> area; 

    public WithinPredicate(CriteriaBuilderImpl criteriaBuilder, Expression<Point> matchExpression, Expression<Geometry> area) { 
     super(criteriaBuilder); 
     this.matchExpression = matchExpression; 
     this.area = area; 
    } 

    public Expression<Point> getMatchExpression() { 
     return matchExpression; 
    } 

    public Expression<Geometry> getArea() { 
     return area; 
    } 

    public void registerParameters(ParameterRegistry registry) { 
     // Nothing to register 
    } 

    @Override 
    public String render(boolean isNegated, RenderingContext renderingContext) { 
     StringBuilder buffer = new StringBuilder(); 
     buffer.append(" within(") 
      .append(((Renderable) getMatchExpression()).render(renderingContext)) 
      .append(", ") 
      .append(((Renderable) getArea()).render(renderingContext)) 
      .append(") = true "); 
     String bo = buffer.toString(); 

     return bo; 
    } 
} 

とクエリの作成から得た述語、。

import com.xxxx.repository.WithinPredicate; 
import com.vividsolutions.jts.geom.Coordinate; 
import com.vividsolutions.jts.geom.Geometry; 
import com.vividsolutions.jts.util.GeometricShapeFactory; 

@Service 
class ... { 
    public List<User> fetchFor(User user) { 
     ... 
     Geometry radius = createCircle(user.getLatitude(), user.getLongitude(), user.getSearchRadius()); 
     radius.setSRID(Location.SRID); 
     p = b.and(p, new WithinPredicate(
      (CriteriaBuilderImpl) b, 
      u.get(User_.location), 
      new LiteralExpression<Geometry>((CriteriaBuilderImpl) b, radius) 
     )); 
    } 

    private static Geometry createCircle(double x, double y, final double RADIUS) { 
     GeometricShapeFactory shapeFactory = new GeometricShapeFactory(); 
     shapeFactory.setNumPoints(32); 
     shapeFactory.setCentre(new Coordinate(x, y));//there are your coordinates 
     shapeFactory.setSize(RADIUS * 2);//this is how you set the radius 
     return shapeFactory.createCircle().getBoundary(); 
    } 
} 

残念ながら、私は出力に乗るエラーがある:Gradleの中

2016-09-09 14:03:30.862 WARN 56393 --- [   main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42883 
2016-09-09 14:03:30.862 ERROR 56393 --- [   main] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: function st_within(geography, bytea) does not exist 
    Hint: No function matches the given name and argument types. You might need to add explicit type casts. 
    Position: 336 

休止状態空間バージョン:

compile('org.hibernate:hibernate-spatial:5.0.9.Final') 

私は疑う問題はおそらくモデルによるものです/スキーマは「Geography(Point、4326)」のタイプに設定されていますが、shapeFactoryは「Geometry(Point、4326)」タイプの半径を作成しています。

本当にありがとうございます。ありがとう。

答えて

1

私はあなたの部分を質問読んだ、しかし、いくつかのものは、いくつかの赤い旗を上げる:

  • あなたは(XY)に軸順序を反転する必要がある、または(経度緯度)
  • あなたがより速くST_DWithinを見つけ、よくためにサポートしますST_Withinは不完全なバッファリングポイント
  • を作成しない、領域内のポイントを見つけるにはgeography
  • のためではない、geometryタイプのために存在しますタイプ。半径の場合、単純にあなたのマイルをメートルに換算してください。
関連する問題