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?
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:
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.