Subversion Repositories hibernate-spatial

Rev

Rev 200 | Rev 203 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?xml version="1.0" encoding="UTF-8"?>

<document>
    <properties>
        <author>Karel Maesen</author>
        <title>Tutorial</title>
    </properties>

    <body>

        <section name="Introduction">
            <p>
                This tutorial gives a quick overview of how to get
                Hibernate Spatial working. We will develop a simple
                application that stores, and retrieves some
                simple data objects. The data objects are "special" in
                that they have a property of type Geometry.
            </p>
            <p>
                This tutorial assumes
                that you are familiar with Hibernate, and the basic
                concepts of working with geographic data. It is also based on the
                <a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html">
                    Hibernate Tutorial</a>and uses the same example. If you
                haven't read the Hibernate Tutorial, and are new to Hibernate, then
                <strong>please read it before proceeding here</strong>.
            </p>
            <p>
                <p>
                    The Hibernate Tutorial uses the HSQLDB in-memory
                    database to keep things simple. Since Hibernate
                    Spatial doesn't (yet) support HSQLDB, we have no
                    such luck. We require a postgis database. For
                    information on how to create a postgis database, you should consult
                    <a href="http://postgis.refractions.net/docs/">the postgis documentation</a>.
                </p>
            </p>
        </section>

        <section name="Creating a Spatially-Enabled EventManager">
            <p>
                We will create a small application to store and retrieve events we want to attend. (This is
                the same use case as in the Hibernate Tutorial).
            </p>
            <subsection name="Setup">
                <p>
                    We first need to set up our development environment. We will use the
                    <a href="http://maven.org/">Maven</a>
                    build tool in this tutorial (as this is also used in the Hibernate Tutorial).
                </p>
                <p>Maven can generate the basic structure of our simple application using the<code>mvn
                    archetype:generate</code>.
                    For this example, we specify type 15 (the default) and set
                    <code>groupId</code>
                    to<code>org.hibernatespatial.tutorials</code>,
                    <code>artifactId</code>
                    to
                    <code>event-tutorial</code>
                    and
                    <code>package</code>
                    to<code>event</code>.
                </p>
                <source>
                    mvn archetype:generate
                    [INFO] Scanning for projects...
                    [INFO] Searching repository for plugin with prefix: 'archetype'.
                    [INFO] ------------------------------------------------------------------------
                    [INFO] Building Maven Default Project
                    [INFO] task-segment: [archetype:generate] (aggregator-style)
                    [INFO] ------------------------------------------------------------------------
                    [INFO] Preparing archetype:generate
                    [INFO] No goals needed for project - skipping
                    [INFO] Setting property: classpath.resource.loader.class =>
                    'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
                    [INFO] Setting property: velocimacro.messages.on => 'false'.
                    [INFO] Setting property: resource.loader => 'classpath'.
                    [INFO] Setting property: resource.manager.logwhenfound => 'false'.
                    [INFO] [archetype:generate {execution: default-cli}]
                    Choose archetype:
                    1: internal -> appfuse-basic-jsf (AppFuse archetype for creating a web application with Hibernate,
                    Spring and JSF)
                    2: internal -> appfuse-basic-spring (AppFuse archetype for creating a web application with
                    Hibernate, Spring and Spring MVC)
                    3: internal -> appfuse-basic-struts (AppFuse archetype for creating a web application with
                    Hibernate, Spring and Struts 2)
                    4: internal -> appfuse-basic-tapestry (AppFuse archetype for creating a web application with
                    Hibernate, Spring and Tapestry 4)
                    5: internal -> appfuse-core (AppFuse archetype for creating a jar application with Hibernate and
                    Spring and XFire)
                    6: internal -> appfuse-modular-jsf (AppFuse archetype for creating a modular application with
                    Hibernate, Spring and JSF)
                    7: internal -> appfuse-modular-spring (AppFuse archetype for creating a modular application with
                    Hibernate, Spring and Spring MVC)
                    8: internal -> appfuse-modular-struts (AppFuse archetype for creating a modular application with
                    Hibernate, Spring and Struts 2)
                    9: internal -> appfuse-modular-tapestry (AppFuse archetype for creating a modular application with
                    Hibernate, Spring and Tapestry 4)
                    10: internal -> maven-archetype-j2ee-simple (A simple J2EE Java application)
                    11: internal -> maven-archetype-marmalade-mojo (A Maven plugin development project using marmalade)
                    12: internal -> maven-archetype-mojo (A Maven Java plugin development project)
                    13: internal -> maven-archetype-portlet (A simple portlet application)
                    14: internal -> maven-archetype-profiles ()
                    15: internal -> maven-archetype-quickstart ()
                    16: internal -> maven-archetype-site-simple (A simple site generation project)
                    17: internal -> maven-archetype-site (A more complex site project)
                    18: internal -> maven-archetype-webapp (A simple Java web application)
                    19: internal -> struts2-archetype-starter (A starter Struts 2 application with Sitemesh, DWR, and
                    Spring)
                    20: internal -> struts2-archetype-blank (A minimal Struts 2 application)
                    21: internal -> struts2-archetype-portlet (A minimal Struts 2 application that can be deployed as a
                    portlet)
                    22: internal -> struts2-archetype-dbportlet (A starter Struts 2 portlet that demonstrates a simple
                    CRUD interface with db backing)
                    23: internal -> struts2-archetype-plugin (A Struts 2 plugin)
                    24: internal -> shale-archetype-blank (A blank Shale web application with JSF)
                    25: internal -> maven-adf-archetype (Archetype to ease the burden of creating a new application
                    based with ADF)
                    26: internal -> data-app (A new Databinder application with sources and resources.)
                    27: internal -> jini-service-archetype (Archetype for Jini service project creation)
                    28: internal -> softeu-archetype-seam (JSF+Facelets+Seam Archetype)
                    29: internal -> softeu-archetype-seam-simple (JSF+Facelets+Seam (no persistence) Archetype)
                    30: internal -> softeu-archetype-jsf (JSF+Facelets Archetype)
                    31: internal -> jpa-maven-archetype (JPA application)
                    32: internal -> spring-osgi-bundle-archetype (Spring-OSGi archetype)
                    33: internal -> confluence-plugin-archetype (Atlassian Confluence plugin archetype)
                    34: internal -> maven-archetype-har (Hibernate Archive)
                    35: internal -> maven-archetype-sar (JBoss Service Archive)
                    36: internal -> wicket-archetype-quickstart (A simple Apache Wicket project)
                    Choose a number:
                    (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36)
                    15: :
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Define value for groupId: : org.hibernatespatial.tutorials
                    Define value for artifactId: : event-tutorial
                    Define value for version: 1.0-SNAPSHOT: :
                    Define value for package: : event
                    Confirm properties configuration:
                    groupId: org.hibernatespatial.tutorials
                    artifactId: event-tutorial
                    version: 1.0-SNAPSHOT
                    package: event
                    Y: : Y
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    Downloading:
                    http://repo1.maven.org/maven2/org/apache/maven/archetypes/maven-archetype-quickstart/1.0/maven-archetype-quickstart-1.0.jar
                    [INFO] ----------------------------------------------------------------------------
                    [INFO] Using following parameters for creating OldArchetype: maven-archetype-quickstart:1.0
                    [INFO] ----------------------------------------------------------------------------
                    [INFO] Parameter: groupId, Value: org.hibernatespatial.tutorials
                    [INFO] Parameter: packageName, Value: event
                    [INFO] Parameter: package, Value: event
                    [INFO] Parameter: artifactId, Value: event-tutorial
                    [INFO] Parameter: basedir, Value: /home/test
                    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
                    [INFO] ********************* End of debug info from resources from generated POM
                    ***********************
                    [INFO] OldArchetype created in dir: /home/test/event-tutorial
                    [INFO] ------------------------------------------------------------------------
                    [INFO] BUILD SUCCESSFUL
                    [INFO] ------------------------------------------------------------------------
                    [INFO] Total time: 36 seconds
                    [INFO] Finished at: Mon Apr 05 17:23:22 CEST 2010
                    [INFO] Final Memory: 15M/158M
                    [INFO] ------------------------------------------------------------------------


                </source>
                <p>This results in the following directory structure.</p>
                <source>
                    event-tutorial/
                    |-- pom.xml
                    `-- src
                    |-- main
                    | `-- java
                    | `-- event
                    | `-- App.java
                    `-- test
                    `-- java
                    `-- event
                    `-- AppTest.java

                </source>
                <p>We now need to edit the pom to add the required dependencies and repositories (see also the<a
                        href="mavenquick.html">Maven Quick Start</a>.).
                </p>
                <source>
                    <![CDATA[
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.hibernatespatial.tutorials</groupId>
    <artifactId>event-tutorial</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>event-tutorial</name>
    <url>http://maven.apache.org</url>

    <build>
         <!-- we dont want the version to be part of the generated war file name -->
         <finalName>${artifactId}</finalName>
    </build>


    <dependencies>

        <!-- Hibernate Spatial for postgis. This will include Hibernate Spatial Core and JTS -->
        <dependency>
            <groupId>org.hibernatespatial</groupId>
            <artifactId>hibernate-spatial-postgis</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- the Postgis JDBC driver -->
        <dependency>
            <groupId>org.postgis</groupId>
            <artifactId>postgis-jdbc</artifactId>
            <version>1.3.5</version>
        </dependency>

        <!-- the postgresql driver -->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>provided</scope>
            <version>8.4-701.jdbc3</version>
        </dependency>

        <!-- Hibernate uses slf4j for logging, for our purposes here use the simple backend -->
               <dependency>
                   <groupId>org.slf4j</groupId>
                   <artifactId>slf4j-simple</artifactId>
                   <version>1.5.11</version>
               </dependency>

    </dependencies>


    <!-- add repositories for JTS and Hibernate Spatial and Hibernate (JBoss) -->
    <repositories>
        <repository>
            <id>OSGEO GeoTools repo</id>
            <url>http://download.osgeo.org/webdav/geotools</url>
        </repository>
        <repository>
            <id>Hibernate Spatial repo</id>
            <url>http://www.hibernatespatial.org/repository</url>
        </repository>
        <!-- add JBOSS repository for easy access to Hibernate libraries -->
        <repository>
            <id>JBOSS</id>
            <url>http://repository.jboss.com/maven2</url>
        </repository>
    </repositories>
</project>
]]>
                </source>

                <p>With the command
                    <code>mvn dependency:list</code>
                    we can see which libraries are required for our minimal
                    Hibernate Spatial application.
                </p>

                <source>
                    mvn dependency:list
                    ....
                    [INFO] The following files have been resolved:
                    [INFO] antlr:antlr:jar:2.7.6:compile
                    [INFO] com.vividsolutions:jts:jar:1.10:compile
                    [INFO] commons-collections:commons-collections:jar:3.1:compile
                    [INFO] dom4j:dom4j:jar:1.6.1:compile
                    [INFO] javassist:javassist:jar:3.11.0.GA:compile
                    [INFO] javax.transaction:jta:jar:1.1:compile
                    [INFO] org.hibernate:hibernate-core:jar:3.3.2.GA:compile
                    [INFO] org.hibernatespatial:hibernate-spatial:jar:1.0:compile
                    [INFO] org.hibernatespatial:hibernate-spatial-postgis:jar:1.0:compile
                    [INFO] org.postgis:postgis-jdbc:jar:1.3.5:compile
                    [INFO] org.slf4j:slf4j-api:jar:1.5.11:compile
                    [INFO] org.slf4j:slf4j-simple:jar:1.5.11:compile
                    [INFO] postgresql:postgresql:jar:8.4-701.jdbc3:provided
                    [INFO] xml-apis:xml-apis:jar:1.0.b2:compile

                </source>
                <p>Hibernate Spatial works with a wide range of versions of these libraries, so don't be too concerned
                    if you see
                    either more recent or slightly older versions.
                </p>

            </subsection>

            <subsection name="The Event Class">
                <p>Our persistent class is the
                    <code>Event</code>
                    class. Since this class
                    contains a geometry-valued property (a property of type Geometry), its instances
                    are geographic objects, or features.
                </p>
                <source>

                    package event;

                    import java.util.Date;

                    import com.vividsolutions.jts.geom.Point;

                    public class Event {
                    private Long id;
                    private String title;
                    private Date date;
                    private Point location;

                    public Event() {
                    }

                    public Long getId() {
                    return id;
                    }

                    private void setId(Long id) {
                    this.id = id;
                    }

                    public Date getDate() {
                    return date;
                    }

                    public void setDate(Date date) {
                    this.date = date;
                    }

                    public String getTitle() {
                    return title;
                    }

                    public void setTitle(String title) {
                    this.title = title;
                    }

                    public Point getLocation() {
                    return this.location;
                    }

                    public void setLocation(Point location) {
                    this.location = location;
                    }
                    }

                </source>
                <p>We put this file in the
                    <code>./src/main/java/event</code>
                    directory of the development directory.
                </p>
            </subsection>

            <subsection name="The Mapping file">
                <p>
                    To map this class to the database table, we create the following Hibernate Mapping file:
                </p>
                <source>
                    <![CDATA[
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="event">
        <class name="Event" table="EVENTS">

        <id name="id" column="EVENT_ID">
                        <generator class="native"/>
                </id>

        <property name="date" type="timestamp" column="EVENT_DATE"/>

        <property name="title" type="string"/>

        <property name="location" type="org.hibernatespatial.GeometryUserType"  column="LOC"/>
        </class>
</hibernate-mapping>
        ]]>
                </source>
                <p>Hibernate Spatial provides the
                    <code>GeometryUserType</code>
                    that enables Hibernate to store the
                    <code>location</code>
                    property properly.
                </p>

                <p>We save this mapping file in
                    <code>./src/main/resources/event/Event.hbm.xml</code>
                    along-side the java source file.
                </p>
            </subsection>
            <subsection name="The Hibernate Configuration">
                <p>
                    We proceed with the hibernate configuration file. The only difference
                    w.r.t. normal Hibernate configurations files is in the dialect
                    property. Hibernate Spatial extends the Hibernate<code>Dialect</code>s so that the spatial
                    features of the database are available within HQL and the
                    <code>SpatialCriteria</code>
                    (see below). So instead of using
                    the (in our case) PostgreSQLDialect, we use Hibernate Spatial's
                    extension of that dialect which is the PostGISDialect.
                    Our
                    <code>hibernate.cfg.xml</code>
                    looks like this:
                    <source>
                        <![CDATA[
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.url">jdbc:postgresql://localhost:5432/events</property>
        <property name="connection.username">postgres</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SPATIAL SQL dialect -->
        <property name="dialect">org.hibernatespatial.postgis.PostgisDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">create</property>

        <mapping resource="event/Event.hbm.xml"/>

    </session-factory>

</hibernate-configuration>              
]]>

                    </source>
                    As is usual when building with maven, we store this file in the
                    <code>./src/main/resources</code>
                    directory.
                </p>
                <p>
                    Note that this configuration file means that Hibernate will connect to the "events"
                    database on localhost, with username "postgres" and no password.
                    (on the test system used, postgres requires no password). You may need to change these
                    values depending on your set-up.
                </p>
                <p>
                    Also notice that the "hbm2dll.auto" property is activated. This will re-create the
                    database everytime the application is run (more precisely when the Hibernate SessionFactory is run).
                </p>
            </subsection>
        </section>

        <subsection name="The HibernateUtil helper">
            The
            <code>HibernatUtil</code>
            class creates the Hibernate SessionFactory for the application, and provides a getter
            to it. (The code below is copied from the Hibernate Tutorial without change).
            <source>
                package util;


                import org.hibernate.*;
                import org.hibernate.cfg.*;

                public class HibernateUtil {

                private static final SessionFactory sessionFactory;

                static {
                try {
                // Create the SessionFactory from hibernate.cfg.xml
                sessionFactory = new Configuration().configure().buildSessionFactory();
                } catch (Throwable ex) {
                // Make sure you log the exception, as it might be swallowed
                System.err.println("Initial SessionFactory creation failed." + ex);
                throw new ExceptionInInitializerError(ex);
                }
                }

                public static SessionFactory getSessionFactory() {
                return sessionFactory;
                }

                }
            </source>

        </subsection>
        <subsection name="The EventManager">
            <p>
                We are now ready to write a first version of the main application class<code>EventManager</code>.
                <source>
                    package event;

                    import org.hibernate.Session;

                    import java.util.Date;

                    import com.vividsolutions.jts.geom.Point;
                    import com.vividsolutions.jts.geom.Geometry;
                    import com.vividsolutions.jts.io.WKTReader;
                    import com.vividsolutions.jts.io.ParseException;

                    import util.HibernateUtil;

                    public class EventManager {

                    public static void main(String[] args) {
                    EventManager mgr = new EventManager();

                    if (args[0].equals("store")) {
                    mgr.createAndStoreEvent("My Event", new Date(), args[1]);
                    }

                    HibernateUtil.getSessionFactory().close();
                    }

                    private void createAndStoreEvent(String title, Date theDate, String wktPoint) {

                    //First interpret the WKT string to a point
                    WKTReader fromText = new WKTReader();
                    Geometry geom = null;
                    try {
                    geom = fromText.read(wktPoint);
                    } catch (ParseException e) {
                    throw new RuntimeException("Not a WKT string:" + wktPoint);
                    }
                    if (!geom.getGeometryType().equals("Point")) {
                    throw new RuntimeException("Geometry must be a point. Got a " + geom.getGeometryType());
                    }

                    Session session = HibernateUtil.getSessionFactory().getCurrentSession();

                    session.beginTransaction();

                    Event theEvent = new Event();
                    theEvent.setTitle(title);
                    theEvent.setDate(theDate);
                    theEvent.setLocation((Point) geom);
                    session.save(theEvent);

                    session.getTransaction().commit();
                    }
                    }

                </source>
                We modified the
                <code>EventManger</code>
                implementation of the Hibernate Tutorial so that it stores
                a point for the event. The point is given as a String in the Well-Known Text (WKT) format. See
                <a href="http://www.vividsolutions.com/jts/javadoc/com/vividsolutions/jts/io/WKTReader.html">the JTS
                    WTKReader JavaDoc
                </a>
                for more information about the WTK format.
            </p>
            <p>
                The development directory now looks like this.
                <source>
                    .
                    |-- event-tutorial.iml
                    |-- event-tutorial.ipr
                    |-- event-tutorial.iws
                    |-- pom.xml
                    `-- src
                    |-- main
                    | |-- java
                    | | |-- event
                    | | | |-- Event.java
                    | | | `-- EventManager.java
                    | | `-- util
                    | | `-- HibernateUtil.java
                    | `-- resources
                    | |-- event
                    | | `-- Event.hbm.xml
                    | `-- hibernate.cfg.xml
                    `-- test
                    `-- java
                    `-- event
                </source>
            </p>
            <p>
                We can now build this program using maven:
                <source>
                    $ mvn compile
                </source>


                We can now execute the program using maven as follows:
                <br/>
                (Note: the backslash in<code>POINT(10\ 0)</code>. this escapes the space in the POINT WKT
                representation.)
                <source>
                    mvn exec:java -Dexec.mainClass="event.EventManager" -Dexec.args="store POINT(10\ 5)"
                </source>

            </p>
            <p>
                This will create the events table, add a new event with the date set to today, the title to "My Title",
                and the point to coordinates (10,15).
            </p>
            We can check the content of the events table using the astext() function that
            converts the geometries to their WKT representation.
            <source>
                events=# select title, astext(loc) from events;

                title | astext
                ----------+--------------
                My Event | POINT(10 15)
                (1 row)
            </source>
        </subsection>
        <subsection name="Spatial Queries">
            <p>We will now modify the
                <code>EventManager</code>
                by adding an action to list all events within a certain area.
                This will show how to use Hibernate Spatial for spatial querying.
            </p>
            <p>
                <strong>Important: comment out the
                    <code>hbm2ddl.auto</code>
                    property in the
                    <code>hibernate.cfg.xml</code>
                    so that
                    the event table is not deleted each time we run the EventManager.
                </strong>
            </p>
            <p>
                Here is the addition to the
                <code>main</code>
                method in the
                <code>EventManager</code>
                that
                implements the "find" action.
                <source>
                    <![CDATA[
...
        if (args[0].equals("store")) {
            mgr.createAndStoreEvent("My Event", new Date(), args[1]);
        }else if (args[0].equals("find")){
            List events = mgr.find(args[1]);
            for (int i = 0; i < events.size(); i++ ){
                    Event event = (Event)events.get(i);
                System.out.println("Event: " + event.getTitle() +
                                ", Time: " + event.getDate() +
                                ", Location: " + event.getLocation());
            }
        }       
...
]]>
                </source>
                We also need to implement the
                <code>find(String filter)</code>
                method.
            </p>
            <p>
                The
                <code>find</code>
                method takes a WKT string that represents a polygon, and
                searches the events table for all events that are located within this polygon.
            </p>
            <p>
                Here is the code.
                <source>
                    <![CDATA[
...
//New imports
import org.hibernate.Criteria;
import java.util.List;
import org.hibernatespatial.criterion.SpatialRestrictions;
...


    private List find(String wktFilter){
        WKTReader fromText = new WKTReader();
        Geometry filter = null;
        try{
                filter = fromText.read(wktFilter);
        } catch(ParseException e){
                throw new RuntimeException("Not a WKT String:" + wktFilter);
        }
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        System.out.println("Filter is : " + filter);
        Criteria testCriteria = session.createCriteria(Event.class);
        testCriteria.add(SpatialRestrictions.within("location", filter));
        List results = testCriteria.list();
        session.getTransaction().commit();
        return results;
    }
...


]]>
                </source>
            </p>
            <p>
                The
                <code>SpatialRestrictions</code>
                class provides utility methods to
                create
                <code>Criterion</code>
                instances for spatial queries. In our
                example the
                <code>WITHIN</code>
                spatial operator is used to query
                all events with a location within a specified filter geometry.
            </p>
            <p>
                The
                <code>witin</code>
                method (as most other methods of<code>SpatialRestrictions</code>) takes
                two parameters. The first is the name of the Geometry-valued property on which the filter
                is applied; the second is the filter geometry.
            </p>
            <p>
                If now run:
                <source>
                    $ mvn exec:java -Dexec.mainClass="event.EventManager" -Dexec.args="find POLYGON((1\ 1,20\ 1,20\
                    20,1\ 20,1\ 1))"
                </source>
                We get
                <source>
                    <![CDATA[
...
Filter is : POLYGON ((1 1, 20 1, 20 20, 1 20, 1 1))
Hibernate: select this_.EVENT_ID as EVENT1_0_0_, this_.EVENT_DATE as EVENT2_0_0_, this_.title as title0_0_, this_.LOC as LOC0_0_ from EVENTS this_ where (this_.LOC && ?  AND   within(this_.LOC, ?))
Event: My Event, Time: 2010-04-05 19:58:36.896, Location: POINT (10 5)
...
]]>
                </source>
                The first line is the Filter that is echoed to<code>System.out</code>, the
                second line is the SQL generated by Hibernate (with the help of Hibernate Spatial).
                This is shown because the
                <code>show_sql</code>
                property is set in the configuration file.
                The last line is the output generated by the
                <code>find</code>
                action.
            </p>

            <p>An alternative approach is using HQL. The Postgis Dialect registers functions and
                operators specified in the the Simple Features for SQL specification. So we could write.
                <source>
                    ...
                    Query q = session
                    .createQuery("from Event where within(location, ?) = true");
                    Type geometryType = GeometryUserType.TYPE;
                    q.setParameter(0, filter, geometryType);
                    List result = q.list();
                    ...
                </source>
                This is pretty much like any other HQL query in Hibernate, with the (slightly annoying)
                complication of having to explicitly specify the
                <code>Type</code>
                for the
                <code>GeometryUserType</code>
                in the<code>setParameter</code>-method.
            </p>

        </subsection>
        <section name="But I use Oracle, so what do I do?">
            <p>Suppose we want to implement the EventManager on top of Oracle, how do we proceed? We
                need to change the following items
                <ol>
                    <li>Replace the
                        <code>hibernate-spatial-postgis-*.jar</code>
                        provider with the
                        <code>hibernate-spatial-oracle-*.jar</code>
                        provider.
                    </li>
                    <li>Replace the Postgresql Driver with the Oracle JDBC Driver.</li>
                    <li>Remove the
                        <code>postgis.jar</code>
                    </li>
                    <li>Modify the
                        <code>hibernate.cfg.xml</code>
                        configuration file so that it
                        points to a suitable Oracle database, uses the Oracle JDBC driver, and has
                        <code>OracleSpatial10gDialect</code>
                        as dialect.
                    </li>
                </ol>
                ... and your done!
            </p>
        </section>

        <section name=".. and what about MySQL?">
            <p>Recent versions of MySQL have (limited) support for spatial types. To get
                Hibernate Spatial to work with MySQL, change the following items:
            </p>
            <ol>
                <li>Replace the
                    <code>hibernate-spatial-postgis-*.jar</code>
                    provider with the
                    <code>hibernate-spatial-mysql-*.jar</code>
                    provider.
                </li>
                <li>Replace the Postgresql Driver with the MySQL JDBC Driver.</li>
                <li>Remove the
                    <code>postgis.jar</code>
                </li>
                <li>Modify the
                    <code>hibernate.cfg.xml</code>
                    configuration file so that it
                    points to a suitable MySQL database, uses the MySQL JDBC driver, and has
                    <code>MySQLSpatialDialect</code>
                    as dialect.
                </li>
            </ol>
            <p>Please note that MySQL's implementation of the spatial types is incomplete at this time. Certain
                functions of Hibernate Spatial will fail at this time.
            </p>
            <p>The MySQLSpatialDialect extends the vanilla MySQLDialect and therefore only supports the MyISAM tables.
            </p>
        </section>

        <section name=".. and what about Microsoft SQL Server 2008?">
            <p>Starting with SQL Server 2008, Microsoft has added full support for OGC Simple Features for SQL. To use
                this database with Hibernate Spatial, change the following items:
            </p>
            <ol>
                <li>Replace the
                    <code>hibernate-spatial-postgis-*.jar</code>
                    provider with the
                    <code>hibernate-spatial-sqlserver-*.jar</code>
                    provider.
                </li>
                <li>Replace the Postgresql Driver with the Microsoft SQL Server JDBC Driver.</li>
                <li>Remove the
                    <code>postgis.jar</code>
                </li>
                <li>Modify the
                    <code>hibernate.cfg.xml</code>
                    configuration file so that it
                    points to a suitable SQL Server database, uses the SQL Server JDBC driver, and has
                    <code>SQLServerSpatialDialect</code>
                    as dialect.
                </li>
            </ol>

        </section>

        <section name="Can I Use JPA Annotations with Hibernate Spatial?">
            <p>
                In stead of using
                <code>*.hbm.xml</code>
                mapping files, you can also use
                JPA annotations. Well almost: JPA doesn't support spatial objects, and doesn't
                have an extension mechanism to add new types. So using only JPA annotations won't work.
                Fortunately, the Hibernate Annotations implementation of JPA does have a means for mapping
                <code>UserType</code>s.
            </p>
            <p>Let's modify the code to use annotations. First, we need to modify the
                <code>pom.xml</code>
                to
                ensure that we build for Java 1.5 (or higher) and to add the Hibernate JPA support libraries.
            </p>

            <source>
                <![CDATA[
    <build>
        ...
        <!-- for JPA we need annotations -->
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
        ...
    </build>


    <dependencies>
        ...
        <!-- add JPA support -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.3.1.GA</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-commons-annotations</artifactId>
            <version>3.3.0.ga</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.3.2.GA</version>
        </dependency>
        ...
    </dependencies>

]]>
            </source>


            <p>We now change the source code of the Events class so that it looks like this</p>
            <source>
                package event;

                import java.util.Date;

                import javax.persistence.*;

                import org.hibernate.annotations.Type;

                import com.vividsolutions.jts.geom.Point;

                @Entity
                @Table(name = "EVENTS")
                public class Event {

                @Id
                @GeneratedValue
                @Column(name = "EVENT_ID")
                private Long id;

                @Column(name = "TITLE")
                private String title;

                @Column(name = "EVENT_DATE")
                private Date date;


                @Column(name = "LOC")
                @Type(type = "org.hibernatespatial.GeometryUserType")
                private Point location;

                public Event() {
                }

                public Long getId() {
                return id;
                }

                private void setId(Long id) {
                this.id = id;
                }

                public Date getDate() {
                return date;
                }

                public void setDate(Date date) {
                this.date = date;
                }

                public String getTitle() {
                return title;
                }

                public void setTitle(String title) {
                this.title = title;
                }

                public Point getLocation() {
                return this.location;
                }

                public void setLocation(Point location) {
                this.location = location;
                }
                }
            </source>
            <p>Note that for the Geometry field we needed
                to use the Hibernate-specific
                <code>@Type</code>
                annotation.
            </p>

            <p>Next, we replace the mapping resource by replacing
                the following line from the
                <code>hibernate.cfg.xml</code>
            </p>

            <source>
                &lt;mapping resource="event/Event.hbm.xml"/&gt;
            </source>
            <p>with a declaration of mapped classes.</p>
            <source>
                &lt;mapping class="event.Event"&gt;
            </source>
            <p>Finally, we change the
                <code>HibernateUtil</code>
                so it uses
                an AnnotationConfiguration object. Change the line:
            </p>
            <source>
                ...
                sessionFactory = new Configuration().configure().buildSessionFactory();
                ...
            </source>
            <p>needs to change to</p>
            <source>
                ...
                sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
                ...
            </source>
            <p>Now the operations should work as before.</p>
        </section>
    </body>
</document>