24
Jan

Meanwhile annotations are preferrred to XML configuration in Java EE. One still can use XML to override annotations. The same is true in JPA: one configures the object-relational mapping via entity annotations. I was in the situtation to make some mappings of the JPA entities and the database tables configurable, when deploying in different environments.

In my situation I needed to switch the ID generation strategy, auto vs. sequence, in all 30+ entites back and forth (building up different database structures for different environments in the same project is a bad thing, but happens in real life…). Either I could change the annotations in each entity file, like I did a few times, or:

  1. Specify with annotations the standard behavior.
  2. Override the annotations with orm.xml.

I will give an example to my situation. In the entity I specified the sequence generation via annotations:

@Id
@SequenceGenerator(name="TABLENAME_ID_GENERATOR", sequenceName="SEQUENCENAME_IN_DB")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLENAME_ID_GENERATOR")
@Column(name="TABLE_ID")
private Long id;

If you start overwriting a property, all annotations on the given property are ignored. So you also have to specify e.g. the @Column-configuration in the xml:
So to overwrite this with strategy=GenerationType.AUTO:

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings  version="1.0"
  xmlns="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemalocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">

  <description>Override Annotations...</description>

  <!-- Set the default to FIELD-access, if you like -->
  <persistence-unit-metadata>
    <persistence-unit-defaults>
      <access>FIELD</access>
    </persistence-unit-defaults>
  </persistence-unit-metadata>

  <entity>
    <attributes>
      <id name="id">
        <column name="TABLE_ID" unique="true" nullable="false" precision="20"/>
        <generated-value strategy="AUTO" />
      </id>
    </attributes>
  </entity>

</entity-mappings>

You are done if you use the default location for this xml, beside the persistence.xml: META-INF/orm.xml.

If you want another name or another location you can register this file in the persistence unit in the persistence.xml:
We rename the file idGenerationStrategyAUTO.xml and then have to specify the mapping-file:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="bigDevPersistenceUnit_DEV" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <mapping-file>META-INF/idGenerationStrategyAUTO.xml</mapping-file>

    <properties>
      ...
    </properties>
  </persistence-unit>
</persistence>

Finally, in the sense of “continous delivery” you could declare different persistence units, e.g. bigDevPersistenceUnit_DEV, bigDevPersistenceUnit_PROD, and create the right entity manager factory by using the detected environment DEV, PROD, see here.

, , ,

One Response to “Overwriting JPA Annotations with orm.xml”

Add reply