Skip to content

HyperJAXB3 Customizing properties and associations

Laurent Schoelens edited this page May 17, 2024 · 1 revision

Customizing properties and associations

In order to customize a schema-derived property you need to associate your annotation with the appropriate XML schema construct. This is typically xs:element or xs:attribute declaration.

Supported customization elements for properties or associations are:

  • hj:id - marks an existing property as identifier property;
  • hj:version - marks an existing property as version property;
  • hj:basic - customizes the basic property;
  • hj:many-to-one - maps X:1 property as many-to-one (default strategy), customizes the many-to-one mapping;
  • hj:one-to-one - maps X:1 property as one-to-one, customizes the one-to-one mapping;
  • hj:one-to-many - maps X:M property as one-to-many (default strategy), customizes the one-to-many mapping;
  • hj:many-to-many - maps X:M property as many-to-many, customizes the many-to-many mapping;
  • hj:embedded - maps the property as embedded, customizes the embedded mapping.
  • hj:generated-id - customizes the generated identifier property.
  • hj:generated-version - instructs Hyperjaxb3 to generate a version property an customizes it.
  • hj:generated-property - customizes artificially generated properties.

Selecting the identifier property

In JPA, every entity must have a primary key. With Hyperjaxb3, you have two options for the primary key: either let Hyperjaxb3 generate a default identifier property for you or mark one of existing properties as identifier property using the hj:id customization element.

In the following example I've selected an existing element id as identifier property, customized column name and the value generation strategy:

<xs:complexType name="myType">
    <xs:sequence>
        <!-- ... -->
        <xs:element name="id" type="xs:int" minOccurs="0">
            <xs:annotation>
                <xs:appinfo>
                    <hj:id>
                        <orm:column name="MY_ID"/>
                        <orm:generated-value strategy="SEQUENCE" generator="my-sequence"/>
                        <orm:sequence-generator name="my-sequence" sequence-name="MY_SEQ"/>
                    </hj:id> 
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <!-- ... -->
    </xs:sequence>
</xs:complexType>

The following customization would surely work as well:

<xs:element name="id" type="xs:int" minOccurs="0">
    <xs:annotation>
        <xs:appinfo>
            <hj:id/>
        </xs:appinfo>
    </xs:annotation>
</xs:element>

Selecting the version property

Similar to marking an existing property as identifier, you may mark an existing property as version property which can be used by persistence provider to perform optimistic locking. Use hj:version customization element for this purpose:

<xs:complexType name="myType">
    <xs:sequence>
        <!-- ... -->
        <xs:element name="lastModified" type="xs:dateTime">
            <xs:annotation>
                <xs:appinfo>
                    <hj:version/>
                </xs:appinfo>
            </xs:annotation>
        </xs:element>
        <!-- ... -->
    </xs:sequence>
</xs:complexType>

Use the nested orm:column element to customize the database column that version property will be mapped to:

<hj:version>
    <orm:column name="MY_VERSION"/>
</hj:version>

Customizing the basic property

Customizing the basic enumerated property

Hyperjaxb3 automatically detects enumerated properties an generates the appropriate @Basic/@Enumerated annotation.

By default, JPA maps enums as strings or integers. You can select enumerated type using hj:basic/orm:enumerated element.

<hj:basic>
    <orm:enumerated>ORDINAL</orm:enumerated>
</hj:basic>

Hyperjaxb3 uses STRING enumerated type per default.

Apart from the default ORDINAL/STRING mappings, Hyperjaxb3 can also map enums by value. Use hj:basic/hj:enumerated-value customization element for this option:

<hj:basic>
    <hj:enumerated-value/>
</hj:basic>

In this case Hyperjaxb3 will generate an additional property which exposes the value of the enum. Generated wrapped property will be persisted, core property will be made transient.

protected Issue143BType issue143B;
 
 
@Transient
public Issue143BType getIssue143B() {
    return issue143B;
}
 
public void setIssue143B(Issue143BType value) {
    this.issue143B = value;
}
 
@Basic
@Column(name = "ISSUE143BITEM", precision = 1, scale = 2)
public Double getIssue143BItem() {
    return ((this.getIssue143B() == null)?null:this.getIssue143B().value());
}
 
public void setIssue143BItem(Double target) {
    setIssue143B(((target == null)?null:Issue143BType.fromValue(target)));
}

Please see tests/enum project for examples of enum customizations.

Customizing the many-to-one property

Customizing the one-to-one property

Customizing the one-to-many property

Order column for one-to-many property

With JPA 2 you can add an order column:

<xsd:element name="person" type="personType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:one-to-many>
                <orm:order-column/>
            </hj:one-to-many>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

You can customize name, nullable, insertable, updatable and column-definition. If you don't provide the name, it will be generated for you:

@OneToMany ...
@OrderColumn(name = "PERSON_ORDER")
public List<PersonType> getPerson() { ... }

Customizing the many-to-many property

Order column for many-to-many property

With JPA 2 you can add an order column:

<xsd:element name="persion" type="personType" minOccurs="0" maxOccurs="unbounded">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:many-to-many>
                <orm:order-column/>
            </hj:many-to-many>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>

See Order column for one-to-many property - it works exactly the same for many-to-many properties.

Customizing the embedded property

Customizing the generated identifier property

In some cases Hyperjaxb3 has to generate an identifier property for the entity. You may use the hj:generated-id customization element to customize this property:

<xs:complexType name="three">
    <xs:annotation>
        <xs:appinfo>
            <hj:generated-id name="ThreeId" attributeName="test:tid" transient="false"/>
        </xs:appinfo>
    </xs:annotation>
    <!-- ... -->
</xs:complexType>

The hj:generated-id customization element has a number of settings like Java type and XML Schema type of the generated id property, its name (in Java) an attribute (in XML) and so on (see Xsddoc on hj:generated-id for details).

One of the most important things worth mentioning here is the transient attribute. It is false by default which means that identifier property will appear as an attribute in XML. You may set it to false - in this case identifier property will be generated as @XmlTransient and will not appear in your XML.

Since 0.5.7 you can use the hj:generated-id customization on mapped superclasses. This will force generation of the identifier property on the mapped superclass.

Customizing the generated version property

By default Hyperjaxb3 does not generate artificial version properties. You can, however, generate a version property by customizing your type with hj:generated-version element:

<xs:complexType name="MyType">
    <xs:annotation>
        <xs:appinfo>
            <hj:generated-version name="Version" attributeName="test:version" transient="false"/>
        </xs:appinfo>
    </xs:annotation>
    <!-- ... -->
</xs:complexType>

See also:

Since 0.5.7 you can use the hj:generated-version customization on mapped superclasses. This will force generation of the version property on the mapped superclass.

Customizing generated properties

Apart from identifier and version, in certain cases Hyperjaxb3 may have to generate additional properties. For instance, consider a construct like:

<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1"/>

Since this "any" property can't be persisted directly with JPA, Hyperjaxb3 will generate an additiona wrapping property. The hj:generated-property customization element allows you to customize this generated property. For instance, you can customize the name of the generated property:

<xs:element name="any" type="xs:anyType">
    <hj:generated-property propertyName="Anything"/>
</xs:element>

Produces:

@XmlElement(required = true)
protected Object any;
 
@Transient
public Object getAny() { ... }
 
public void setAny(Object value) { ... }
 
@Basic
@Column(name = "ANYTHING")
public String getAnything() { ... }
public void setAnything(String target) { ... }

The hj:generated-property element can be specified in the bindings of the originating property (as shown above) or in the bindings of the class. In this case you must provide specify the name of the originating property in the name attribute:

<xsd:complexType name="....">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:generated-property name="Any" propertyName="Anything">
                <!-- ... -->
            </hj:generated-property>
        </xsd:appinfo>
    </xsd:annotation>
    <xsd:sequence>
        <!--
         ! Schema-derived property named "Any" with be accompanied
         ! by a generated wrapping property named "Anything" (see above)
         !-->
        <xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1"/>
    </xsd:sequence>
</xsd:complexType> 

As of 2.1.13, JAXB RI seems to have a problem processing customizations for `xsd:any. You can only customize such properties via the parent class as shown above.

Contents of the hj:generated-property will be used as customizations for the wrapping property. For instance, you could customize the mapping of the generated property:

<xsd:element name="any" type="xsd:anyType">
    <xsd:annotation>
        <xsd:appinfo>
            <hj:generated-property propertyName="Anything">
                <hj:basic merged="false">
                    <orm:column name="EVERYTHING" length="3000"/>
                </hj:basic>
            </hj:generated-property>
        </xsd:appinfo>
    </xsd:annotation>
</xsd:element>
Clone this wiki locally