Merge remote-tracking branch 'upstream/master' into wip/6.0
This commit is contained in:
commit
4e22c5cabc
|
@ -0,0 +1,4 @@
|
||||||
|
.asciidoctor
|
||||||
|
*.png
|
||||||
|
*.html
|
||||||
|
*.pdf
|
|
@ -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<JaxbHbmHibernateMapping>
|
||||||
|
|
||||||
|
@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<Document>
|
||||||
|
|
||||||
|
@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
|
||||||
|
----
|
||||||
|
|
||||||
|
##
|
|
@ -684,7 +684,7 @@ Sets the associated collection cache concurrency strategy for the designated reg
|
||||||
=== Infinispan properties
|
=== Infinispan properties
|
||||||
|
|
||||||
For more details about how to customize the Infinispan second-level cache provider, check out the
|
For more details about how to customize the Infinispan second-level cache provider, check out the
|
||||||
http://infinispan.org/docs/stable/user_guide/user_guide.html#configuration_properties[Infinispan User Guide].
|
http://infinispan.org/docs/stable/titles/integrating/integrating.html#configuration_properties[Infinispan User Guide].
|
||||||
|
|
||||||
[[configurations-transactions]]
|
[[configurations-transactions]]
|
||||||
=== Transactions properties
|
=== Transactions properties
|
||||||
|
|
|
@ -707,4 +707,4 @@ Infinispan is a distributed in-memory key/value data store, available as a cache
|
||||||
It supports advanced functionality such as transactions, events, querying, distributed processing, off-heap and geographical failover.
|
It supports advanced functionality such as transactions, events, querying, distributed processing, off-heap and geographical failover.
|
||||||
|
|
||||||
For more details, check out the
|
For more details, check out the
|
||||||
http://infinispan.org/docs/stable/user_guide/user_guide.html#integrations_jpa_hibernate[Infinispan User Guide].
|
http://infinispan.org/docs/stable/titles/integrating/integrating.html#integrating_jpa_hibernate[Infinispan User Guide].
|
|
@ -8,7 +8,7 @@ package org.hibernate.boot.archive.internal;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.boot.archive.spi.ArchiveContext;
|
import org.hibernate.boot.archive.spi.ArchiveContext;
|
||||||
import org.hibernate.boot.archive.spi.ArchiveDescriptor;
|
import org.hibernate.boot.archive.spi.ArchiveDescriptor;
|
||||||
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
|
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;
|
||||||
|
|
|
@ -86,6 +86,8 @@ import org.hibernate.id.factory.IdentifierGeneratorFactory;
|
||||||
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.SessionFactoryImpl;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
import org.hibernate.mapping.Column;
|
import org.hibernate.mapping.Column;
|
||||||
|
|
|
@ -1083,7 +1083,7 @@ public class BinderHelper {
|
||||||
if ( declaringClass != null ) {
|
if ( declaringClass != null ) {
|
||||||
final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
|
final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
|
||||||
if ( inheritanceState == null ) {
|
if ( inheritanceState == null ) {
|
||||||
throw new org.hibernate.annotations.common.AssertionFailure(
|
throw new AssertionFailure(
|
||||||
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import javax.persistence.Convert;
|
||||||
import javax.persistence.Converts;
|
import javax.persistence.Converts;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
|
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
|
|
@ -31,6 +31,7 @@ import javax.persistence.MapKeyColumn;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.BatchSize;
|
import org.hibernate.annotations.BatchSize;
|
||||||
|
@ -64,7 +65,6 @@ import org.hibernate.annotations.SortNatural;
|
||||||
import org.hibernate.annotations.SortType;
|
import org.hibernate.annotations.SortType;
|
||||||
import org.hibernate.annotations.Where;
|
import org.hibernate.annotations.Where;
|
||||||
import org.hibernate.annotations.WhereJoinTable;
|
import org.hibernate.annotations.WhereJoinTable;
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import javax.persistence.Id;
|
||||||
import javax.persistence.Lob;
|
import javax.persistence.Lob;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.annotations.AttributeAccessor;
|
import org.hibernate.annotations.AttributeAccessor;
|
||||||
import org.hibernate.annotations.Generated;
|
import org.hibernate.annotations.Generated;
|
||||||
|
@ -20,7 +21,6 @@ import org.hibernate.annotations.Immutable;
|
||||||
import org.hibernate.annotations.NaturalId;
|
import org.hibernate.annotations.NaturalId;
|
||||||
import org.hibernate.annotations.OptimisticLock;
|
import org.hibernate.annotations.OptimisticLock;
|
||||||
import org.hibernate.annotations.ValueGenerationType;
|
import org.hibernate.annotations.ValueGenerationType;
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
import org.hibernate.annotations.common.reflection.XProperty;
|
import org.hibernate.annotations.common.reflection.XProperty;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
|
|
|
@ -12,8 +12,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
import javax.validation.Path;
|
import javax.validation.Path;
|
||||||
import javax.validation.TraversableResolver;
|
import javax.validation.TraversableResolver;
|
||||||
|
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.annotations.common.util.StringHelper;
|
|
||||||
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
|
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
|
||||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
@ -21,6 +20,7 @@ import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
|
||||||
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
|
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,10 @@ import javax.naming.event.NamingExceptionEvent;
|
||||||
import javax.naming.spi.ObjectFactory;
|
import javax.naming.spi.ObjectFactory;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.annotations.common.util.StringHelper;
|
|
||||||
import org.hibernate.engine.jndi.JndiException;
|
import org.hibernate.engine.jndi.JndiException;
|
||||||
import org.hibernate.engine.jndi.JndiNameException;
|
import org.hibernate.engine.jndi.JndiNameException;
|
||||||
import org.hibernate.engine.jndi.spi.JndiService;
|
import org.hibernate.engine.jndi.spi.JndiService;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A registry of all {@link SessionFactory} instances for the same classloader as this class.
|
* A registry of all {@link SessionFactory} instances for the same classloader as this class.
|
||||||
|
|
|
@ -17,10 +17,10 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.annotations.common.util.StringHelper;
|
|
||||||
import org.hibernate.boot.model.relational.Exportable;
|
import org.hibernate.boot.model.relational.Exportable;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A relational constraint.
|
* A relational constraint.
|
||||||
|
|
|
@ -16,8 +16,8 @@ import javax.persistence.OneToOne;
|
||||||
import javax.persistence.metamodel.Attribute;
|
import javax.persistence.metamodel.Attribute;
|
||||||
import javax.persistence.metamodel.Type;
|
import javax.persistence.metamodel.Type;
|
||||||
|
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.internal.HEMLogging;
|
import org.hibernate.internal.HEMLogging;
|
||||||
import org.hibernate.mapping.Collection;
|
import org.hibernate.mapping.Collection;
|
||||||
|
|
|
@ -23,7 +23,8 @@ import javax.persistence.metamodel.Type;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.annotations.common.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.EntityManagerMessageLogger;
|
import org.hibernate.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.internal.HEMLogging;
|
import org.hibernate.internal.HEMLogging;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.jpa.test.criteria.size;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Expression;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH014245")
|
||||||
|
public class CriteriaSelectSizeCollectionTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Customer.class, Alias.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Customer customer = new Customer( "1", "Phil" );
|
||||||
|
Alias alias = new Alias( "2", "p" );
|
||||||
|
customer.addAlias( alias );
|
||||||
|
entityManager.persist( customer );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectCollectionSize() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Integer> query = criteriaBuilder.createQuery( Integer.class );
|
||||||
|
Root<Customer> customer = query.from( Customer.class );
|
||||||
|
|
||||||
|
Expression<Integer> aliases = criteriaBuilder.size( customer.get( "aliases" ) );
|
||||||
|
query.select( aliases );
|
||||||
|
query.where( criteriaBuilder.equal( customer.get( "id" ), "1" ) );
|
||||||
|
|
||||||
|
TypedQuery<Integer> tq = entityManager.createQuery( query );
|
||||||
|
Integer size = tq.getSingleResult();
|
||||||
|
assertThat( size, is( 1 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Customer")
|
||||||
|
@Table(name = "CUSTOMER_TABLE")
|
||||||
|
public static class Customer {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToMany(cascade = CascadeType.ALL)
|
||||||
|
private Collection<Alias> aliases = new ArrayList<>();
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(String id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAlias(Alias alias) {
|
||||||
|
aliases.add( alias );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Alias")
|
||||||
|
@Table(name = "ALIAS_TABLE")
|
||||||
|
public static class Alias implements java.io.Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
|
||||||
|
public Alias() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Alias(String id, String alias) {
|
||||||
|
this.id = id;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue