-
Notifications
You must be signed in to change notification settings - Fork 17
Object ontological Mapping
Object-ontological mapping (OOM) in JOPA is, much like in JPA, realized via annotations in Java.
The annotations tell JOPA which classes it should consider as entity classes, which of their attributes are persistent and to what ontological properties they are mapped.
The most important annotations in this regard are:
@OWLClass
is placed on a Java class and specifies that this class is a part of the persistence unit metamodel. It has one attribute - iri
- whose value maps the class to the corresponding RDFS/OWL class.
@Id
marks field which contains the instance's identifier (IRI in ontological terms). Supported types are String
, java.net.URI
and java.net.URL
.
The identifier can be marked as generated
, so that when an instance with an empty identifier is persisted, JOPA will generate the identifier value.
@OWLObjectProperty
marks Java attributes which reference other objects. In OWL, this corresponds to object properties, which link individuals to other individuals. RDF makes no such distinction.
However, for JOPA, the distinction between @OWLObjectProperty
and other kinds of properties (see below) is important. They tell it whether it should expect a literal value (like an integer, String) or a resource's identifier. Therefore, when using RDF-based storage like RDF4J, @OWLObjectProperty
should still be used, marking fields whose type is either another entity class or String
/java.net.URI
/java.net.URL
. In case the type is String
/URI
/URL
, JOPA will assume that the intended value is an individual's identifier (this is referred to as plain identifier object property in Javadoc and source code. No other types can be used for fields annotated with @OWLObjectProperty
.
The iri
attribute represents the property to which the annotated attribute is mapped.
fetch
specifies whether the attribute value should be eagerly or lazily loaded (it is supposed to work the same as in JPA). Note that when using data access objects, it is usually better to have the fetch
set to eager. Since JOPA currently does not support extended persistence contexts, once the loaded object becomes detached from the persistence context (usually when returned from DAO/service with transactional entity manager), lazily loaded attributes may be null
without any way to load them. Defaults to FetchType.LAZY
.
cascade
whether entity manager operations should be cascaded over this attribute. This works the same way as in cascading in JPA.
@OWLDataProperty
marks a literal-valued field. This corresponds to an OWL datatype property. Again, RDF does not care about this distinction, but JOPA will assume the value to be a literal and treat it as such. The annotated fields should not used Java primitive types but their wrapper equivalents, i.e. Integer
for int
etc.
The iri
attribute represents the property to which the annotated attribute is mapped.
fetch
works same as above. It defaults to FetchType.EAGER
for data properties.
lexicalForm
allows to load the property value into a String
regardless of the type of the literal. This functionality, however, has a limitation - such an attribute would be read-only. This is because when the field is a String representing lexical form of the literal, JOPA has no way of knowing what the type of the literal should be when saving it (e.g., on persist, or even on update). Updating could thus lead to unintentional changes in the data. A safer way is thus to prevent modification of such values.
@OWLAnnotationProperty
correspond to OWL annotation properties. The notion is not known in RDF, so when accessing RDF-based storages, this annotation can be ignored and OWLDataProperty
used instead. However, when using OWL-based storage (i.e. currently only OWL API), the distinctions between different kinds of properties are significant.
The iri
attribute represents the property to which the annotated attribute is mapped.
fetch
works same as above. It defaults to FetchType.EAGER
for annotation properties.
lexicalForm
works the same way as above. If the annotation value is an resource/individual, its identifier is loaded into the attribute. The read-only conditions, however, applies to it as well.
Below is a simple example of a JOPA entity, which makes use of all the aforementioned kinds of properties:
@OWLClass(iri = Vocabulary.s_c_Occurrence)
public class Occurrence {
@Id
private URI uri;
@OWLDataProperty(iri = Vocabulary.s_p_has_key)
private String key;
@OWLAnnotationProperty(iri = CommonVocabulary.RDFS_LABEL)
private String name;
OWLObjectProperty(iri = Vocabulary.s_p_has_part, fetch = FetchType.EAGER, cascade = {CascadeType.MERGE,
CascadeType.REMOVE})
private Set<Event> children;
// Getters and setters follow
}
Note that currently the property annotations have to be placed on the fields, getter/setter annotations are not supported.
If a field should not persistent, on of the following mechanisms can be used:
- Field is
static
- Field is
transient
- Field is annotated with
@Transient