为Geoerver增加自定义空间数据(二)

来源:互联网 发布:龙虎榜数据实时查询app 编辑:程序博客网 时间:2024/06/10 18:52

前面说过SQLDialect被用于屏蔽各种数据库SQL的差异,可以理解为策略模式。凡是涉及到sql的,均由该类来处理。

SQLDialect是一个抽象类,该类继承结构相对就很简单了:

 

选择直接从BasicSQLDialect派生自己的Dialect。派生后有4个必须实现的函数,如下:

l         encodeGeometryValue (Geometry value, int srid, StringBuffer sql)

根据Geometry对象,生成sql语句。

由于只是为GeoServer增加自定义数据源,并不涉及到空间数据的修改,因此可以不为用encodeGeometryValue函数写代码。

 

l        decodeGeometryEnvelope(ResultSet rs, int column,Connection cx)

rs中获取Geometry的包围盒大小,生成Envelope对象并返回。

 

l         decodeGeometryValue(ResultSet rs, int column,Connection cx)

rs中获取Geometry数据,构造Geometry对象并返回。

 

l         encodeGeometryEnvelope(String tableName, String geometryColumn,StringBuffer sql)

该函数是用于构造获取指定表的Envelopesql语句,

代码如下:

    public void encodeGeometryEnvelope(String tableName, String geometryColumn, StringBuffer sql) {

           sql.append(FeatureClassInfo.XMIN_FIELD_NAME + "," + FeatureClassInfo.XMAX_FIELD_NAME  + "," +

             FeatureClassInfo.YMIN_FIELD_NAME  + "," + FeatureClassInfo.YMAX_FIELD_NAME );

    }

 

 

但是在一般情况下,仅仅这4个函数并不能满足需求。

l         includeTable(String schemaName, String tableName, Connection cx)

该函数用于判断指定的表名是否是空间数据表。

 

l         getGeometrySRID(String schemaName, String tableName,String columnName, Connection cx)

该函数用于返回指定表的SRID(整型)。

 

l         encodeColumnAlias(String raw, StringBuffer sql)

l         getMapping(ResultSet columnMetaData, Connection cx)

该函数用来说明当前表保存的是哪种类型的空间数据。如果点状要素,则返回Point.Classcom.vividsolutions.jts.geom),以此类推。如果不确定则返回Geometry.class或者null

代码如下:

    public Class<?> getMapping(ResultSet columnMetaData, Connection cx)

            throws SQLException {

   

        String name = columnMetaData.getString("TYPE_NAME");

   

       if ( name.equalsIgnoreCase("image") == false ) {

           return null;

       }

              

       String tableName = columnMetaData.getString("TABLE_NAME");

             

    AccessHelper  helper = new AccessHelper(cx);

   

        GisDBHelper       gisdb = new GisDBHelper();

   

        FeatureClassInfo fci = gisdb.getFeatureClassInfo(helper, tableName);

   

    if ( fci.getShapeType() == GisGeometryType.gisGeoTypePoint )

        return Point.class;

    else if ( fci.getShapeType() == GisGeometryType.gisGeoTypePolyline )

        return MultiLineString.class;

    else if ( fci.getShapeType() == GisGeometryType.gisGeoTypePolygon )

        return MultiPolygon.class;

       

    return null;

    }

 

另外,值得说的是主键查找器。这里为了得到主键,gt里定义了一个抽象类PrimaryKeyFinder,并且有相应的实现类。不过由于自定义数据源,因此并不能直接使用gt中现有的类。为此,从PrimaryKeyFinder派生了一个子类负责返回主键,代码如下:

public class GisPrimaryKeyFinder extends PrimaryKeyFinder {

 

    @Override

    public PrimaryKey getPrimaryKey(JDBCDataStore store, String schema,

           String table, Connection cx) throws SQLException {

       // TODO Auto-generated method stub

    AccessHelper  helper = new AccessHelper(cx);

   

    FeatureClassInfo fci = GisDBHelper.getFeatureClassInfo(helper, table);

   

    PrimaryKey pk = null;

        

    if ( fci != null )

    {

        List<PrimaryKeyColumn> keys = new ArrayList<PrimaryKeyColumn>();

           

        keys.add(new NonIncrementingPrimaryKeyColumn(fci.getOidFieldName(),

               Integer.class));

       

        pk = new PrimaryKey(table, keys);

    }

       helper.closeStatement();

      

       return pk;

    }

}

 

那么这个类在什么地方和JDBCDataStore关联起来?

就在数据源工厂类的createSQLDialect方法中,代码如下:

    protected SQLDialect createSQLDialect(JDBCDataStore dataStore)

    {

    dataStore.setPrimaryKeyFinder(new GisPrimaryKeyFinder());

   

    return new KqGisSqlServerSQLDialect(dataStore);

    }

 

通过以上代码就可以实现自定义的空间数据源(数据库型)。

 

PS:实现自定义的数据源其实并不复杂,大量的时间花在了研究GeoServer和GeoTools中。

 

原创粉丝点击