Skip to content
Alexey Valikov edited this page Aug 31, 2017 · 1 revision

JPA 2 Support

JPA 2 support

Hyperjaxb3 supports JPA 2 since version 0.5.6.

Generating JPA 2 metadata

Use the jpa2 variant to generate JPA 2 annotations:

Maven:

<plugin>
    <groupId>org.jvnet.hyperjaxb3</groupId>
    <artifactId>maven-hyperjaxb3-plugin</artifactId>
    <configuration>
        <variant>jpa2</variant>
    </configuration>
</plugin>

Ant:

<xjc destdir="${basedir}/target/generated-sources/xjc" extension="true">
    <arg line="
        -Xhyperjaxb3-jpa2
        -Xhyperjaxb3-jpa2-roundtripTestClassName=RoundtripTest
        -Xequals
        -Xinheritance
        -XhashCode
        -XtoString"/>
    <binding dir="${basedir}/src/main/resources">
        <include name="**/*.xjb"/>
    </binding>
    <schema dir="${basedir}/src/main/resources">
        <include name="**/*.xsd"/>
    </schema>
    <classpath>
        <fileset dir="${basedir}/lib">
            <include name="*.jar"/>
        </fileset>
    </classpath>
</xjc>

Icon Hyperjaxb3 can generate JPA 2 annotations as well as XML mapping files according to the JPA 2 according to the JPA 2 orm_2_0.xsd XML schema. Use <result>mappingFiles</result> or -Xhyperjaxb3-jpa2-result=mappingFiles configuration items accordingly.

Supported JPA 2 features

Collections of simple types

JPA 2 supports collections of simple types using the @ElementCollection annotation. Hyperjaxb3 uses this feature to improve mapping of the repeatable simple type elements.

Example:

<xsd:complexType name="HJIII-63-Alpha">
    <xsd:sequence>
        <xsd:element name="stringElements" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element name="dateElements" type="xsd:date" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
</xsd:complexType>

Generates:

    @ElementCollection
    @OrderColumn(name = "HJINDEX")
    @Column(name = "HJVALUE", length = 255)
    @CollectionTable(name = "HJIII63ALPHA_STRINGELEMENTS", joinColumns = {
        @JoinColumn(name = "HJID")
    })
    public List<String> getStringElements() { ... }


    @ElementCollection
    @OrderColumn(name = "HJINDEX")
    @Column(name = "HJVALUE", precision = 20, scale = 10)
    @CollectionTable(name = "HJIII63ALPHA_DECIMALELEMENTS", joinColumns = {
        @JoinColumn(name = "HJID")
    })
    public List<BigDecimal> getDecimalElements() { ... }

Improved embedding

In JPA 2, @Embeddable mechanism is much more powerful when compared to to JPA 1. Embeddable classes can now have complex properties, associations, collections - and even nested embeddables. Hyperjaxb3 now supportes @Embeddable features.

Example:

    <xs:element name="unit" type="UnitType"/>

    <xs:complexType name="UnitType">
        <xs:sequence>
            <xs:element name="head" type="PersonType"/>
            <xs:element name="address" type="AddressType"/>
        </xs:sequence>
    </xs:complexType>   

    <xs:complexType name="PersonType">
        <xs:annotation>
            <xs:appinfo>
                <hj:embeddable/>
            </xs:appinfo>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="AddressType"/>
        </xs:sequence>
    </xs:complexType>   

    <xs:complexType name="AddressType">
        <xs:annotation>
            <xs:appinfo>
                <hj:embeddable/>
            </xs:appinfo>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="street" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="state" type="xs:string" minOccurs="0"/>
            <xs:element name="zip" type="xs:string"/>
            <xs:element name="country" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>   

Note that both PersonType as well as AddressType are embeddable. Moreover, PersonType has a nested embeddable (address).

Generates:

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "name", column = @Column(name = "HEAD_NAME", length = 255)),
        @AttributeOverride(name = "address.street", column = @Column(name = "HEAD_ADDRESS_STREET", length = 255)),
        @AttributeOverride(name = "address.city", column = @Column(name = "HEAD_ADDRESS_CITY", length = 255)),
        @AttributeOverride(name = "address.state", column = @Column(name = "HEAD_ADDRESS_STATE", length = 255)),
        @AttributeOverride(name = "address.zip", column = @Column(name = "HEAD_ADDRESS_ZIP", length = 255)),
        @AttributeOverride(name = "address.country", column = @Column(name = "HEAD_ADDRESS_COUNTRY", length = 255))
    })
    public PersonType getHead() { ... }

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "street", column = @Column(name = "ADDRESS_STREET", length = 255)),
        @AttributeOverride(name = "city", column = @Column(name = "ADDRESS_CITY", length = 255)),
        @AttributeOverride(name = "state", column = @Column(name = "ADDRESS_STATE", length = 255)),
        @AttributeOverride(name = "zip", column = @Column(name = "ADDRESS_ZIP", length = 255)),
        @AttributeOverride(name = "country", column = @Column(name = "ADDRESS_COUNTRY", length = 255))
    })
    public AddressType getAddress() { ... }

Here's how it looks like in the database:

create table UNITTYPE (
    HJID bigint generated by default as identity (start with 1),
    ADDRESS_CITY varchar(255),
    ADDRESS_COUNTRY varchar(255),
    ADDRESS_STATE varchar(255),
    ADDRESS_STREET varchar(255),
    ADDRESS_ZIP varchar(255),
    HEAD_ADDRESS_CITY varchar(255),
    HEAD_ADDRESS_COUNTRY varchar(255),
    HEAD_ADDRESS_STATE varchar(255),
    HEAD_ADDRESS_STREET varchar(255),
    HEAD_ADDRESS_ZIP varchar(255),
    HEAD_NAME varchar(255), primary key (HJID))

Note that column names for both embeddable AddressType fields do not collide.

Clone this wiki locally