diff --git a/design/.gitignore b/design/.gitignore new file mode 100644 index 0000000000..e048586ab8 --- /dev/null +++ b/design/.gitignore @@ -0,0 +1,4 @@ +.asciidoctor +*.png +*.html +*.pdf \ No newline at end of file diff --git a/design/mapping-model.adoc b/design/mapping-model.adoc new file mode 100644 index 0000000000..1d70d40160 --- /dev/null +++ b/design/mapping-model.adoc @@ -0,0 +1,424 @@ +:link-parallelArrays: https://en.wikipedia.org/wiki/Parallel_array["parallel arrays"] += Domain Model Mappings + +:toc2: +:toclevels: 3 +:sectanchors: +:numbered: + +Describes Hibernate's handling of domain model metadata + +== Mapping sources + +Mapping sources include `hbm.xml` files, `orm.xml` files and annotated classes. There are +other specialized forms of sources, but they all come back to locating annotated classes +and XML mappings. + +The main actors in managing the sources include: + +`MetadataSources`:: +Used to collect mapping sources to be processed together + +`JaxbHbmHibernateMapping`:: +Main JAXB binding for a `hbm.xml` mapping document + +`Binding`:: +Represents an XML mapping within the `MetadataSources`. Wraps either a +`JaxbHbmHibernateMapping` or DOM `Document` representing a JPA `orm.xml`. + +`MappingBinder`:: +Responsible for generating `Binding` instances. + +The handling for XML mappings is as follows: + +[plantuml,hbm,png] +.hbm.xml processing +---- +@startuml +skinparam handwritten true + +Application -> MetadataSources : add(hbm.xml) +MetadataSources -> MappingBinder : parse(hbm.xml) +MappingBinder -> JAXB : bind(hbm.xml) +MappingBinder <- JAXB : JaxbHbmHibernateMapping +MetadataSources <- MappingBinder : Binding + +@enduml +---- + +[plantuml,orm,png] +.orm.xml processing +---- +@startuml +skinparam handwritten true + +Application -> MetadataSources : add(orm.xml) +MetadataSources -> MappingBinder : parse(orm.xml) +MappingBinder -> DOM : bind(orm.xml) +MappingBinder <- DOM : Document +MetadataSources <- MappingBinder : Binding + +@enduml +---- + +NOTE: `MetadataSources` receives XML files without any knowledge of whether the file +is a Hibernate mapping (`hbm.xml`) or a JPA mapping (`orm.xml`). `MappingBinder` makes +that distinction based on doctype, schema, etc. + + +== Boot-time metamodel + +The `org.hibernate.mapping` package defines most of the boot-time model. + + +[plantuml,bootmodel,png] +.Boot model actors +---- +@startmindmap +skinparam handwritten true ++ Boot model +++ PersistentClass +++ Property +++ Value +++ IdGenerator +++ TypeDef +-- Table +-- Selectable +-- PrimaryKey +-- Constraint +@endmindmap +---- + +=== PersistentClass + +Models an entity + +[plantuml,persistentclass,png] +.PersistentClass hierarchy +---- +@startuml +interface Value + +class Property +Property -- Value : value > + +class PersistentClass { + entityName : String +} +PersistentClass *- Property : properties > + +class RootClass { + table : Table +} + +class JoinedSubclass { + table : Table +} + +class UnionSubclass { + table : Table +} + +PersistentClass <|-- RootClass +PersistentClass <|-- Subclass +Subclass <|-- JoinedSubclass +Subclass <|-- SingleTableSubclass +Subclass <|-- UnionSubclass +@enduml +---- + + +=== Value + +Models a value. A value ultimately corresponds to a `org.hibernate.type.Type`. We will discuss +this "simple" distinction when we talk about Types in the run-time metamodel section. + + +[plantuml,value,png] +.Value hierarchy +---- +@startuml +class SimpleValue +note left of SimpleValue : By itself represents\na basic value +class OneToMany +note top of OneToMany : Used as element descriptor for\none-to-many collections + +Value <|-- KeyValue +Value <|-- OneToMany + +KeyValue <|-- SimpleValue + +SimpleValue <|-- DependentValue + +SimpleValue <|-- Component + +SimpleValue <|-- Any + +SimpleValue <|-- ToOne +ToOne <|-- ManyToOne +ToOne <|-- OneToOne + +Value <|-- Collection +Collection <|-- Bag +Collection <|-- Set +Collection <|-- IdentifierCollection +IdentifierCollection <|-- IdentifierBag +Collection <|-- IndexedCollection +IndexedCollection <|-- List +List <|-- Array +IndexedCollection <|-- Map + +@enduml +---- + + +=== Database model + +[plantuml,db,png] +.Database model +---- +@startuml +class Identifier +Identifier : String text +Identifier : boolean quoted + +Selectable <|-- Column +Column : Identifider name + +Selectable <|-- Formula +Formula : String fragment + +Constraint <|-- PrimaryKey +Constraint <|-- UniqueKey +Constraint <|-- ForeignKey + +class Table +Table : Identifier name +Table : Identifier schema +Table : Identifier catalog +Table : PrimaryKey : primaryKey +Table : Selectable : selectables + +class Index +class Sequence + +interface Exportable +Exportable <|-- Table +Exportable <|-- Constraint +Exportable <|-- Index +Exportable <|-- Sequence +Exportable <|-- AuxilaryDatabaseObject + +interface TableOwner +TableOwner : Table table + +TableOwner <|-- RootClass +TableOwner <|-- JoinedSubclass +TableOwner <|-- UnionSubclass +@enduml +---- + + +=== Transition from sources to boot-time model + +The boot-time metamodel is built iteratively. The general paradigm in this transition is to +instantiate one of these boot-time objects which are then populated in multiple later steps (via +setters, additions, etc). + +The main actors in this process are `HbmMetadataSourceProcessorImpl` and `AnnotationMetadataSourceProcessorImpl`. + + +[plantuml,source2boot,png] +.Transition sources to boot-time model +---- +@startuml +skinparam handwritten true +autonumber + +Application -> MetadataBuilder : build() +MetadataBuilder -> MetadataBuildingProcess : build() +MetadataBuildingProcess -> MetadataSourceProcessor + +MetadataSourceProcessor -> HbmMetadataSourceProcessorImpl : process hbm.xml Bindings + +MetadataSourceProcessor -> AnnotationMetadataSourceProcessorImpl : process annotations + orm.xml Bindings + +MetadataBuilder <- MetadataBuildingProcess : Metadata +Application <- MetadataBuilder : Metadata + +@enduml +---- + + +== Run-time metamodel + + +[plantuml,runtimemodel,png] +.Run-time model actors +---- +@startmindmap +skinparam handwritten true ++ Boot model +++ EntityPersister +++ CollectionPersister +++ Tuplizer +-- Type +-- IdentifierGenerator +@endmindmap +---- + +=== EntityPersister + +Manages persistence of an entity to/from its defined table(s). Maintains flattened +state regarding various aspects of the entity's value mappings as {link-parallelArrays}. +An entity's value mappings include: + * identifier + * attribute state + * (discriminator) + * (version) + +[plantuml,entitypersister,png] +.EntityPersister hierarchy +---- +@startuml +skinparam handwritten true +interface EntityPersister + +abstract class AbstractEntityPersister +EntityPersister <|-- AbstractEntityPersister + +AbstractEntityPersister <|-- SingleTableEntityPersister +AbstractEntityPersister <|-- JoinedEntityPersister +AbstractEntityPersister <|-- UnionEntityPersister +@enduml +---- + + +=== CollectionPersister + +Manages persistence of a collection to its defined table(s). Maintains flattened +state as {link-parallelArrays} regarding various aspects of the value mappings making +up the collection. These aspects include: + * key -- the FK + * element + * (identifier) -- @IdBag + * (list-index | map-key) + +[plantuml,collectionpersister,png] +.CollectionPersister hierarchy +---- +@startuml +skinparam handwritten true +interface CollectionPersister + +abstract class AbstractCollectionPersister +CollectionPersister <|-- CollectionPersister + +AbstractCollectionPersister <|-- BasicCollectionPersister +AbstractCollectionPersister <|-- OneToManyCollectionPersister + +note left of BasicCollectionPersister : collection mappings\nwith a collection table +@enduml +---- + +=== Type + +Describes a value mapping which is some form of non-identified state. + +[plantuml,type,png] +.Type hierarchy +---- +@startuml +skinparam handwritten true + +interface Type + +interface IdentifierType +Type <|-- IdentifierType + +interface DiscriminatorType +IdentifierType <|-- DiscriminatorType + +interface VersionType +Type <|-- VersionType + +interface BasicType +Type <|-- BasicType + +interface CompositeType +Type <|-- CompositeType +CompositeType *- Type : subtypes + +interface AssociationType +Type <|-- AssociationType + +interface AnyType { + discriminatorType : DiscriminatorType + identifierType : IdentifierType +} +AssociationType <|-- AnyType +CompositeType <|-- AnyType + +interface UserType +interface CustomType +CustomType -- UserType : wrappedUserType +Type <|-- CustomType +@enduml +---- + +`IdentifierType`:: +Specialized Type contract for types that can be used as an identifier + +`DiscriminatorType`:: +Specialized Type contract for types that can be used as a discriminator + +`VersionType`:: +Specialized Type contract for types that can be used as a version + +`BasicType`:: +Mapping to a single column + +`CompositeType`:: +Mapping to one or more columns + +`AssociationType`:: +Mapping to an entity association + +`AnyType`:: +Models a discriminated association which is similar to an association referencing a +discriminated-subclass entity in that the mapping involves a discriminator. However, +in an ANY mapping the discriminator is on the referring side. This will map to at least +2 columns - one for the discriminator plus one or more identifier columns. + +`EntityType`:: +Models a foreign-key, which "from this side" is a to-one. Could map to a single column or multiple. + +`CollectionType`:: +Models a foreign-key, which "from this side" is a to-many. Will map to at + + +=== Transition from boot-time model to run-time model + +This transition involves processing the boot model objects (`PersistentClass`, `Value`, etc) and building +the corresponding run-time counterparts (`EntityPersister`, `Type`, etc). + +The main actors in this transition are the `SessionFactory` itself, `MetamodelImplementor` and +`TypeConfiguration`: + + +[plantuml,boot2run,png] +.Transition boot-time model to run-time model +---- +@startuml +skinparam handwritten true + +Application -> SessionFactoryBuilder : build() +SessionFactoryBuilder -> SessionFactory : new +SessionFactory -> TypeConfiguration : scope + +... + +@enduml +---- + +## \ No newline at end of file