Teneo supports JPA 2.0 annotations, additional Hibernate annotation extensions and adds several convenience annotations.
The JPA specification contains a description of each annotation. Download the spec from here).
Hibernate Annotations Extensions
In addition to the JPA annotations, Teneo supports a number of Hibernate Annotations Extensions.
The following Hibernate specific annotations are supported:
- AnyMetaDef (only on EReferences, not on EPackage, meta-value not yet supported)
- Entity (is called HbEntity in Teneo to prevent name-clashes)
- FilterDef and Filter
- ForeignKey (only name attribute)
- Index (only the name attribute)
- Named query
- NaturalId (only the mutable of the first natural id in an entity is used)
- Proxy (limited testing done)
- Type (on EAttribute)
- TypeDef (on EDataType) Where (tested on association, also available on EClass level)
In Addition the following Teneo specific annotation(s) are supported:
- ListIndexColumn: used to define the index column name.
In future releases the support for hibernate specific annotations will be extended.
Not supported annotations
- @Cacheable is not supported because of this hibernate issue
- @MapsId: if the MapsId has a value then generator foreign is not supported
- @MapKeyClass: actually not needed as EMF always generates typed collections
@Entity annotation has a new field: extends
The @Entity annotation has a new field which is not specified in the jpa spec: extends. This annotation can be used to handle multiple-inheritance, see here for more information
Annotations on EDataType
Every JPA annotation which is relevant for a non-reference type java member can also be specified on an EDataType. Setting annotations on an EDataType has as advantage that the annotation is used in every location in which the EDataType is used. For example the column length annotation can be defined on EDataType level and is then automatically added to each EAttribute which uses this EDataType. The annotations on EAttribute level take precedence so if both the EAttribute and the EDataType have the same annotation then the annotation on the EAttribute is used.
External annotation: persisting references to external/non-persisted objects
Teneo allows you to persist references to objects in a custom way. To support this the @External annotation can be used. This annotation as a default will persist a reference as a String/varchar column containing the URI of the object. The annotation has a type attribute which can be used to specify your own hibernate UserType to completely customize the reference persistence.
See here for more information
Transient on EClass
The Transient annotation can also be used on an EClass. This prevents an EClass from being mapped and be persisted.
This means also that in case that the super EClass of an EClass is transient that the properties of the super EClass are not persisted and that the sub EClass requires its own identifier/primary key properties.
Derby and IDBAG issue
There is an issue with the combination of Derby and IDBAG, see here for more information.
Unique annotation added to OneToMany to force a join table for 1:n relations
In a relational database 1:n relations are often modeled by adding a foreign-key (to the parent) in the child table/object. The disadvantage of this approach is that duplicates are not supported. To support duplicates in an elist a join table is required. To signal to Teneo, that a join table should be used, the annotation as in this example can be used:
<xsd:element name="joinedItem" type="xsd:anyURI" ecore:reference="this:Item" maxOccurs="unbounded"> <xsd:annotation> <xsd:appinfo source="teneo.jpa">@OneToMany(unique=false)</xsd:appinfo> </xsd:annotation> </xsd:element>
Based on this annotations Teneo will generate a join table for this model. Note that this annotation can be combined with the indexed annotation.
The unique annotation does not exist in the EJB3 spec and is a Teneo extension.
The http://annotation.elver.org/Indexed annotation can be used to signal to Elver that a certain association does not require an index column and has a bag like behavior. See here for more information.
EmbeddedID lets you use an embedded class as an entity's composite primary key.
Note: in general, composite primary keys are only necessary for legacy data models. It's strongly recommended to use single (non-composite) keys for new data models.
Teneo requires that the composite key's class is an EObject, as it needs ECore metadata to define the correct mapping.
Some database engines - for example, MySQL - have different BLOB types for different data sizes. (TINYBLOB, MEDIUMBLOB, LARGEBLOB.)
The actual BLOB type used by Hibernate is thus dependent upon the column length, but the default column length of 255 is often too small to acommodate typical BLOB data.
Therefore you'll need to add a Column.length annotation to the property specifying the maximum possible size of the BLOB data, as shown below:
<xsd:element name="photo" type="xsd:base64Binary" minOccurs="0"> <xsd:annotation> <!-- Map to a 'binary' field. --> <xsd:appinfo source="teneo.jpa"> @Lob <!-- Use 1Mb maximum length. (MEDIUMBLOB in MySQL.) --> @Column(length=1048576) </xsd:appinfo> </xsd:annotation> </xsd:element>
EMF ID Attribute
When an eattribute has its ID property set to true and there is no @Id annotated eattribute in the eclass then the ID eattribute is used. This default behavior can be changed using the option: ID_FEATURE_AS_PRIMARY_KEY.
Extra CASCADE type: NONE
Teneo will automatically set the cascade annotation when no cascade annotation has been set on an assocation. To also support no-cascading behavior the additional CascadeType NONE is supported by Teneo.