简体   繁体   中英

using jaxb, hyperjaxb3, jpa2, jts, hibernate-spatial, postgis fails when hyperjaxb marks the JTS Point getter as @Transient

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM