My coworkers lament my adherence to code generation, but I'm determined to prove this particular chain can be done. Examples below are simplified from my project (and thus untested as typed); I will create a test harness soon. Currently using hibernate 4.1.4, hibernate-spatial 1.1.1, hyperjaxb3-ejb-plugin 0.5.6.

I start off with a schema that uses a Position element whose type is a simple string extension:

  <xsd:simpleType name="wktPoint">
    <xsd:restriction base="xsd:string">
    </xsd:restriction>
  </xsd:simpleType>

I use bindings.xjb customizations to map my xmlType wktPoint to a JTS Point javaType using jaxb:javaType, since I will want to map the JTS Point field to a postgis geometry column:

<jaxb:javaType name="com.vividsolutions.jts.geom.Point" xmlType="wktPoint" parseMethod="test.Reader.readWKTPoint" printMethod="test.Writer.writeWKTPoint" />

Later in the bindings.xjb, I start customizing the Position element using annox:annotation:

<jaxb:bindings node="xsd:complexType[@name='MyType']//xsd:element[@name='Position']">
  <annox:annotate target="getter">
    <annox:annotate annox:class="javax.persistence.Basic"/>        
    <annox:annotate annox:class="javax.persistence.Column" name="POSITION" columnDefinition="GEOMETRY"/>
    <annox:annotate annox:class="org.hibernate.annotations.Type" type="org.hibernatespatial.GeometryUserType">
      <annox:annotate annox:field="parameters">
        <annox:annotate annox:class="org.hibernate.annotations.Parameter" name="dialect" value="postgis"/>
      </annox:annotate>
    </annox:annotate>
  </annox:annotate>      
</jaxb:bindings>

However, this produces the following getPosition method in MyType.java:

/**
 * Gets the value of the position property.
 * @return
 *     possible object is
 *     {@link String }
 */
@Transient
@Basic
@Column(columnDefinition = "GEOMETRY", name = "POSITION")
@Type(parameters = {
    @Parameter(name = "dialect", value = "postgis")
}, type = "org.hibernatespatial.GeometryUserType")
public Point getPosition() {
    return position;
}

So when I start up my application and jpa/hibernate starts initializing the tables, it skips the POSITION column altogether (since it got marked @Transient).

How can I prevent @Transient from showing up? It seems I need to convince Hyperjaxb that we will be able to write the JTS Point type directly to the database (that's what all the @Type stuff is about, signaling that we want hibernatespatial to use the postgis dialect when reading and writing Positions). Any ideas on how to do that?

1

There are 1 answers

2
jesse crossley On

The 0.5.6 hyperjaxb-ejb-plugin just doesn't handle the binding customization properly. I built a 0.5.7-SNAPSHOT that modified the org.jvnet.hyperjaxb3.ejb.strategy.mapping AttributesMapping.getAttributeMapping() so that my customized jaxb binding would no longer be labelled Transient. I gave it the following fallback check:

if (isFieldOutlineBasic(fieldOutline)) {
    ...
} else if (isFieldOutlineComplex(fieldOutline)) {
    ...
} else {
    if (fieldOutline.getRawType() instanceof JClass) {
        return context.getBasicMapping();
    }
}

This covered my customization, which would always show up as a JDirectClass(Point). Once I made that change, the postgis tables were created with the correct geometry types, and I can now take in a WKT Point string, have it unmarshall as a JTS Point, and then persist it with JPA as a PostGIS geometry. I did also need to rebuild Hibernate Spatial (now using a 1.1.2-SNAPSHOT) to work with Hibernate4. I'll submit this work to Karel Maesen and I'll also submit the Hyperjaxb change to Aleksei Valikov and hopefully future versions will be that much more robust.