mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-22 11:06:08 +00:00
HHH-13041 - Move @Any and other association mappings to the association chapter
This commit is contained in:
parent
06b559e46e
commit
fecb12cff7
@ -633,14 +633,14 @@ You should use either the JPA <<annotations-jpa-access>> or the Hibernate native
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Any.html[`@Any`] annotation is used to define the *any-to-one* association
|
||||
which can point to one one of several entity types.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-any,`@Any` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-anymetadef]]
|
||||
==== `@AnyMetaDef`
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyMetaDef.html[`@AnyMetaDef`] annotation is used to provide metadata about an `@Any` or `@ManyToAny` mapping.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-any,`@Any` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-anymetadefs]]
|
||||
==== `@AnyMetaDefs`
|
||||
@ -816,14 +816,14 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Filter.html[`@Filter`] annotation is used to add filters to an entity or the target entity of a collection.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-filter-example,Filter mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-filter,Filter mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-filterdef]]
|
||||
==== `@FilterDef`
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/FilterDef.html[`@FilterDef`] annotation is used to specify a `@Filter` definition (name, default condition and parameter types, if any).
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-filter-example,Filter mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-filter,Filter mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-filterdefs]]
|
||||
==== `@FilterDefs`
|
||||
@ -835,7 +835,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/FilterJoinTable.html[`@FilterJoinTable`] annotation is used to add `@Filter` capabilities to a join table collection.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-filter-join-table,FilterJoinTable mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-filter-join-table,FilterJoinTable mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-filterjointables]]
|
||||
==== `@FilterJoinTables`
|
||||
@ -907,7 +907,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinColumnOrFormula.html[`@JoinColumnOrFormula`] annotation is used to specify that the entity association is resolved either through a FOREIGN KEY join (e.g. <<annotations-jpa-joincolumn>>) or using the result of a given SQL formula (e.g. <<annotations-hibernate-joinformula>>).
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-JoinColumnOrFormula,`@JoinColumnOrFormula` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-JoinColumnOrFormula,`@JoinColumnOrFormula` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-joincolumnsorformulas]]
|
||||
==== `@JoinColumnsOrFormulas`
|
||||
@ -918,7 +918,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinFormula.html[`@JoinFormula`] annotation is used as a replacement for <<annotations-jpa-joincolumn>> when the association does not have a dedicated FOREIGN KEY column.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-JoinFormula,`@JoinFormula` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-JoinFormula,`@JoinFormula` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-lazycollection]]
|
||||
==== `@LazyCollection`
|
||||
@ -983,7 +983,7 @@ See the <<chapters/query/native/Native.adoc#sql-custom-crud-example, Custom CRUD
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/ManyToAny.html[`@ManyToAny`] annotation is used to specify a many-to-one association when the target type is dynamically resolved.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-many-to-any, `@ManyToAny` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-many-to-any, `@ManyToAny` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-mapkeytype]]
|
||||
==== `@MapKeyType`
|
||||
@ -997,7 +997,7 @@ See the <<chapters/domain/collections.adoc#collections-map-custom-key-type, `@Ma
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/MetaValue.html[`@MetaValue`] annotation is used by the <<annotations-hibernate-anymetadef>> annotation to specify the association between a given discriminator value and an entity type.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-any,`@Any` mapping>> section for more info.
|
||||
See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-namednativequeries]]
|
||||
==== `@NamedNativeQueries`
|
||||
@ -1122,7 +1122,7 @@ See the <<chapters/domain/collections.adoc#collections-customizing-ordered-by-sq
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/ParamDef.html[`@ParamDef`] annotation is used in conjunction with <<annotations-hibernate-filterdef>> so that the Hibernate Filter can be customized with runtime-provided parameter values.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-filter-example,Filter mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-filter-example,Filter mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-parameter]]
|
||||
==== `@Parameter`
|
||||
@ -1135,7 +1135,7 @@ like <<annotations-hibernate-collectiontype>>, <<annotations-hibernate-genericge
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Parent.html[`@Parent`] annotation is used to specify that the currently annotated embeddable attribute references back the owning entity.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-Parent,`@Parent` mapping>> section for more info.
|
||||
See the <<chapters/domain/embeddables.adoc#embeddable-Parent,`@Parent` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-persister]]
|
||||
==== `@Persister`
|
||||
@ -1237,7 +1237,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
|
||||
The alias (e.g. `myAlias`) can then be used in the `@Filter` `condition` clause using the `{alias}` (e.g. `{myAlias}`) placeholder.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-column-filter-sql-fragment-alias,`@SqlFragmentAlias` mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-filter-sql-fragment-alias,`@SqlFragmentAlias` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-sqlinsert]]
|
||||
==== `@SQLInsert`
|
||||
@ -1287,7 +1287,7 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
|
||||
==== `@Target`
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Target.html[`@Target`] annotation is used to specify an explicit target implementation when the currently annotated association is using an interface type.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-Target,`@Target` mapping>> section for more info.
|
||||
See the <<chapters/domain/embeddables.adoc#embeddable-Target,`@Target` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-tuplizer]]
|
||||
==== `@Tuplizer`
|
||||
@ -1349,11 +1349,11 @@ See the <<chapters/domain/basic_types.adoc#mapping-database-generated-value-exam
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Where.html[`@Where`] annotation is used to specify a custom SQL `WHERE` clause used when fetching an entity or a collection.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-where-example,`@Where` mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-where-example,`@Where` mapping>> section for more info.
|
||||
|
||||
[[annotations-hibernate-wherejointable]]
|
||||
==== `@WhereJoinTable`
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/WhereJoinTable.html[`@WhereJoinTable`] annotation is used to specify a custom SQL `WHERE` clause used when fetching a join collection table.
|
||||
|
||||
See the <<chapters/domain/basic_types.adoc#mapping-where-join-table, `@WhereJoinTable` mapping>> section for more info.
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-where-join-table, `@WhereJoinTable` mapping>> section for more info.
|
||||
|
@ -485,3 +485,276 @@ Hibernate is not going to throw any exception, and it will assign a value of `nu
|
||||
include::{sourcedir}/NotFoundTest.java[tags=associations-not-found-non-existing-find-example,indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
[[associations-any]]
|
||||
==== `@Any` mapping
|
||||
|
||||
The `@Any` mapping is useful to emulate a unidirectional `@ManyToOne` association when there can be multiple target entities.
|
||||
|
||||
Because the `@Any` mapping defines a polymorphic association to classes from multiple tables,
|
||||
this association type requires the FK column which provides the associated parent identifier and
|
||||
a metadata information for the associated entity type.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is impossible to specify a foreign key constraint for this kind of association.
|
||||
This is not the usual way of mapping polymorphic associations and you should use this only in special cases (e.g. audit logs, user session data, etc).
|
||||
====
|
||||
|
||||
The `@Any` annotation describes the column holding the metadata information.
|
||||
To link the value of the metadata information and an actual entity type, the `@AnyDef` and `@AnyDefs` annotations are used.
|
||||
The `metaType` attribute allows the application to specify a custom type that maps database column values to persistent classes that have identifier properties of the type specified by `idType`.
|
||||
You must specify the mapping from values of the `metaType` to class names.
|
||||
|
||||
For the next examples, consider the following `Property` class hierarchy:
|
||||
|
||||
[[associations-any-property-example]]
|
||||
.`Property` class hierarchy
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/Property.java[tags=associations-any-property-example]
|
||||
|
||||
include::{sourcedir}/any/IntegerProperty.java[tags=associations-any-property-example]
|
||||
|
||||
include::{sourcedir}/any/StringProperty.java[tags=associations-any-property-example]
|
||||
----
|
||||
====
|
||||
|
||||
A `PropertyHolder` can reference any such property, and, because each `Property` belongs to a separate table, the `@Any` annotation is, therefore, required.
|
||||
|
||||
[[associations-any-example]]
|
||||
.`@Any` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/PropertyHolder.java[tags=associations-any-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-any-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
As you can see, there are two columns used to reference a `Property` instance: `property_id` and `property_type`.
|
||||
The `property_id` is used to match the `id` column of either the `string_property` or `integer_property` tables,
|
||||
while the `property_type` is used to match the `string_property` or the `integer_property` table.
|
||||
|
||||
The table resolving mapping is defined by the `metaDef` attribute which references an `@AnyMetaDef` mapping.
|
||||
Although the `@AnyMetaDef` mapping could be set right next to the `@Any` annotation,
|
||||
it's good practice to reuse it, therefore it makes sense to configure it on a class or package-level basis.
|
||||
|
||||
The `package-info.java` contains the `@AnyMetaDef` mapping:
|
||||
|
||||
[[associations-any-meta-def-example]]
|
||||
.`@Any` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/package-info.java[tags=associations-any-meta-def-example]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is recommended to place the `@AnyMetaDef` mapping as a package metadata.
|
||||
====
|
||||
|
||||
To see the `@Any` annotation in action, consider the next examples.
|
||||
|
||||
If we persist an `IntegerProperty` as well as a `StringProperty` entity, and associate
|
||||
the `StringProperty` entity with a `PropertyHolder`,
|
||||
Hibernate will generate the following SQL queries:
|
||||
|
||||
[[associations-any-persist-example]]
|
||||
.`@Any` mapping persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/AnyTest.java[tags=associations-any-persist-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-any-persist-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `PropertyHolder` entity and navigating its `property` association,
|
||||
Hibernate will fetch the associated `StringProperty` entity like this:
|
||||
|
||||
[[associations-any-query-example]]
|
||||
.`@Any` mapping query example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/AnyTest.java[tags=associations-any-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-any-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[associations-many-to-any]]
|
||||
===== `@ManyToAny` mapping
|
||||
|
||||
While the `@Any` mapping is useful to emulate a `@ManyToOne` association when there can be multiple target entities,
|
||||
to emulate a `@OneToMany` association, the `@ManyToAny` annotation must be used.
|
||||
|
||||
In the following example, the `PropertyRepository` entity has a collection of `Property` entities.
|
||||
|
||||
The `repository_properties` link table holds the associations between `PropertyRepository` and `Property` entities.
|
||||
|
||||
[[associations-many-to-any-example]]
|
||||
.`@ManyToAny` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/PropertyRepository.java[tags=associations-many-to-any-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-many-to-any-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
To see the `@ManyToAny` annotation in action, consider the next examples.
|
||||
|
||||
If we persist an `IntegerProperty` as well as a `StringProperty` entity,
|
||||
and associate both of them with a `PropertyRepository` parent entity,
|
||||
Hibernate will generate the following SQL queries:
|
||||
|
||||
[[associations-many-to-any-persist-example]]
|
||||
.`@ManyToAny` mapping persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/ManyToAnyTest.java[tags=associations-many-to-any-persist-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-many-to-any-persist-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `PropertyRepository` entity and navigating its `properties` association,
|
||||
Hibernate will fetch the associated `IntegerProperty` and `StringProperty` entities like this:
|
||||
|
||||
[[associations-many-to-any-query-example]]
|
||||
.`@ManyToAny` mapping query example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/any/ManyToAnyTest.java[tags=associations-many-to-any-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-many-to-any-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[associations-JoinFormula]]
|
||||
==== `@JoinFormula` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinFormula.html[`@JoinFormula`] annotation is used to customize the join between a child Foreign Key and a parent row Primary Key.
|
||||
|
||||
[[associations-JoinFormula-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinFormulaTest.java[tags=associations-JoinFormula-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-JoinFormula-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The `country` association in the `User` entity is mapped by the country identifier provided by the `phoneNumber` property.
|
||||
|
||||
Considering we have the following entities:
|
||||
|
||||
[[associations-JoinFormula-persistence-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinFormulaTest.java[tags=associations-JoinFormula-persistence-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `User` entities, the `country` property is mapped by the `@JoinFormula` expression:
|
||||
|
||||
[[associations-JoinFormula-fetching-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinFormulaTest.java[tags=associations-JoinFormula-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-JoinFormula-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@JoinFormula` annotation is used to define a custom join association between the parent-child association.
|
||||
|
||||
[[associations-JoinColumnOrFormula]]
|
||||
==== `@JoinColumnOrFormula` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinColumnOrFormula.html[`@JoinColumnOrFormula`] annotation is used to customize the join between a child Foreign Key and a parent row Primary Key when we need to take into consideration a column value as well as a `@JoinFormula`.
|
||||
|
||||
[[associations-JoinColumnOrFormula-example]]
|
||||
.`@JoinColumnOrFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinColumnOrFormulaTest.java[tags=associations-JoinColumnOrFormula-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-JoinColumnOrFormula-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The `country` association in the `User` entity is mapped by the `language` property value and the associated `Country` `is_default` column value.
|
||||
|
||||
Considering we have the following entities:
|
||||
|
||||
[[associations-JoinColumnOrFormula-persistence-example]]
|
||||
.`@JoinColumnOrFormula` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinColumnOrFormulaTest.java[tags=associations-JoinColumnOrFormula-persistence-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `User` entities, the `country` property is mapped by the `@JoinColumnOrFormula` expression:
|
||||
|
||||
[[associations-JoinColumnOrFormula-fetching-example]]
|
||||
.`@JoinColumnOrFormula` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/JoinColumnOrFormulaTest.java[tags=associations-JoinColumnOrFormula-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/associations-JoinColumnOrFormula-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@JoinColumnOrFormula` annotation is used to define a custom join association between the parent-child association.
|
||||
|
@ -1718,736 +1718,3 @@ include::{extrasdir}/basic/mapping-column-formula-persistence-example.sql[]
|
||||
====
|
||||
The SQL fragment can be as complex as you want and even include subselects.
|
||||
====
|
||||
|
||||
[[mapping-column-where]]
|
||||
==== `@Where`
|
||||
|
||||
Sometimes, you want to filter out entities or collections using custom SQL criteria.
|
||||
This can be achieved using the `@Where` annotation, which can be applied to entities and collections.
|
||||
|
||||
[[mapping-where-example]]
|
||||
.`@Where` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereTest.java[tags=mapping-where-example]
|
||||
----
|
||||
====
|
||||
|
||||
If the database contains the following entities:
|
||||
|
||||
[[mapping-where-persistence-example]]
|
||||
.Persisting and fetching entities with a `@Where` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereTest.java[tags=mapping-where-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-where-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When executing an `Account` entity query, Hibernate is going to filter out all records that are not active.
|
||||
|
||||
[[mapping-where-entity-query-example]]
|
||||
.Query entities mapped with `@Where`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereTest.java[tags=mapping-where-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-where-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `debitAccounts` or the `creditAccounts` collections, Hibernate is going to apply the `@Where` clause filtering criteria to the associated child entities.
|
||||
|
||||
[[mapping-where-collection-query-example]]
|
||||
.Traversing collections mapped with `@Where`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereTest.java[tags=mapping-where-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-where-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-where-join-table]]
|
||||
==== `@WhereJoinTable`
|
||||
|
||||
Just like `@Where` annotation, `@WhereJoinTable` is used to filter out collections using a joined table (e.g. @ManyToMany association).
|
||||
|
||||
[[mapping-where-join-table-example]]
|
||||
.`@WhereJoinTable` mapping example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereJoinTableTest.java[tags=mapping-where-join-table-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-where-join-table-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
In the example above, the current week `Reader` entities are included in the `currentWeekReaders` collection
|
||||
which uses the `@WhereJoinTable` annotation to filter the joined table rows according to the provided SQL clause.
|
||||
|
||||
Considering that the following two `Book_Reader` entries are added into our system:
|
||||
|
||||
[[mapping-where-join-table-persist-example]]
|
||||
.`@WhereJoinTable` test data
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereJoinTableTest.java[tags=mapping-where-join-table-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `currentWeekReaders` collection, Hibernate is going to find one one entry:
|
||||
|
||||
[[mapping-where-join-table-fetch-example]]
|
||||
.`@WhereJoinTable` fetch example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/WhereJoinTableTest.java[tags=mapping-where-join-table-fetch-example]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-column-filter]]
|
||||
==== `@Filter`
|
||||
|
||||
The `@Filter` annotation is another way to filter out entities or collections using custom SQL criteria.
|
||||
Unlike the `@Where` annotation, `@Filter` allows you to parameterize the filter clause at runtime.
|
||||
|
||||
Now, considering we have the following `Account` entity:
|
||||
|
||||
[[mapping-filter-account-example]]
|
||||
.`@Filter` mapping entity-level usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-Account-example]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Notice that the `active` property is mapped to the `active_status` column.
|
||||
|
||||
This mapping was done to show you that the `@Filter` condition uses a SQL condition and not a JPQL filtering predicate.
|
||||
====
|
||||
|
||||
As already explained, we can also apply the `@Filter` annotation for collections as illustrated by the `Client` entity:
|
||||
|
||||
[[mapping-filter-client-example]]
|
||||
.`@Filter` mapping collection-level usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-Client-example]
|
||||
----
|
||||
====
|
||||
|
||||
If we persist a `Client` with three associated `Account` entities,
|
||||
Hibernate will execute the following SQL statements:
|
||||
|
||||
[[mapping-filter-persistence-example]]
|
||||
.Persisting and fetching entities with a `@Filter` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
By default, without explicitly enabling the filter, Hibernate is going to fetch all `Account` entities.
|
||||
|
||||
[[mapping-no-filter-entity-query-example]]
|
||||
.Query entities mapped without activating the `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-no-filter-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-no-filter-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
If the filter is enabled and the filter parameter value is provided,
|
||||
then Hibernate is going to apply the filtering criteria to the associated `Account` entities.
|
||||
|
||||
[[mapping-filter-entity-query-example]]
|
||||
.Query entities mapped with `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
Filters apply to entity queries, but not to direct fetching.
|
||||
|
||||
Therefore, in the following example, the filter is not taken into consideration when fetching an entity from the Persistence Context.
|
||||
|
||||
[[mapping-filter-entity-example]]
|
||||
.Fetching entities mapped with `@Filter`
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-entity-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-entity-example.sql[]
|
||||
----
|
||||
|
||||
As you can see from the example above, contrary to an entity query, the filter does not prevent the entity from being loaded.
|
||||
====
|
||||
|
||||
Just like with entity queries, collections can be filtered as well, but only if the filter is explicitly enabled on the currently running Hibernate `Session`.
|
||||
|
||||
[[mapping-no-filter-collection-query-example]]
|
||||
.Traversing collections without activating the `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-no-filter-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-no-filter-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When activating the `@Filter` and fetching the `accounts` collections, Hibernate is going to apply the filter condition to the associated collection entries.
|
||||
|
||||
[[mapping-filter-collection-query-example]]
|
||||
.Traversing collections mapped with `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The main advantage of `@Filter` over the `@Where` clause is that the filtering criteria can be customized at runtime.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
It's not possible to combine the `@Filter` and `@Cache` collection annotations.
|
||||
This limitation is due to ensuring consistency and because the filtering information is not stored in the second-level cache.
|
||||
|
||||
If caching were allowed for a currently filtered collection, then the second-level cache would store only a subset of the whole collection.
|
||||
Afterward, every other Session will get the filtered collection from the cache, even if the Session-level filters have not been explicitly activated.
|
||||
|
||||
For this reason, the second-level collection cache is limited to storing whole collections, and not subsets.
|
||||
====
|
||||
|
||||
[[mapping-column-filter-join-table]]
|
||||
==== `@FilterJoinTable`
|
||||
|
||||
When using the `@Filter` annotation with collections, the filtering is done against the child entries (entities or embeddables).
|
||||
However, if you have a link table between the parent entity and the child table, then you need to use the `@FilterJoinTable` to filter child entries according to some column contained in the join table.
|
||||
|
||||
The `@FilterJoinTable` annotation can be, therefore, applied to a unidirectional `@OneToMany` collection as illustrated in the following mapping:
|
||||
|
||||
[[mapping-filter-join-table-example]]
|
||||
.`@FilterJoinTable` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-filter-join-table-example]
|
||||
----
|
||||
====
|
||||
|
||||
The `firstAccounts` filter will allow us to get only the `Account` entities that have the `order_id`
|
||||
(which tells the position of every entry inside the `accounts` collection)
|
||||
less than a given number (e.g. `maxOrderId`).
|
||||
|
||||
Let's assume our database contains the following entities:
|
||||
|
||||
[[mapping-filter-join-table-persistence-example]]
|
||||
.Persisting and fetching entities with a `@FilterJoinTable` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-filter-join-table-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-join-table-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The collections can be filtered only if the associated filter is enabled on the currently running Hibernate `Session`.
|
||||
|
||||
[[mapping-no-filter-join-table-collection-query-example]]
|
||||
.Traversing collections mapped with `@FilterJoinTable` without enabling the filter
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-no-filter-join-table-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-no-filter-join-table-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
If we enable the filter and set the `maxOrderId` to `1` when fetching the `accounts` collections, Hibernate is going to apply the `@FilterJoinTable` clause filtering criteria, and we will get just
|
||||
`2` `Account` entities, with the `order_id` values of `0` and `1`.
|
||||
|
||||
[[mapping-filter-join-table-collection-query-example]]
|
||||
.Traversing collections mapped with `@FilterJoinTable`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-filter-join-table-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-join-table-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-column-filter-sql-fragment-alias]]
|
||||
==== `@Filter` with `@SqlFragmentAlias`
|
||||
|
||||
When using the `@Filter` annotation and working with entities that are mapped onto multiple database tables,
|
||||
you will need to use the
|
||||
https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/SqlFragmentAlias.html[`@SqlFragmentAlias`] annotation
|
||||
if the `@Filter` defines a condition that uses predicates across multiple tables.
|
||||
|
||||
[[mapping-filter-sql-fragment-alias-example]]
|
||||
.`@SqlFragmentAlias` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterSqlFragementAliasTest.java[tags=mapping-filter-sql-fragment-alias-example]
|
||||
----
|
||||
====
|
||||
|
||||
Now, when fetching the `Account` entities and activating the filter,
|
||||
Hibernate is going to apply the right table aliases to the filter predicates:
|
||||
|
||||
[[mapping-filter-sql-fragment-alias-query-example]]
|
||||
.Fetching a collection filtered with `@SqlFragmentAlias`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/FilterSqlFragementAliasTest.java[tags=mapping-filter-sql-fragment-alias-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-filter-sql-fragment-alias-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-column-any]]
|
||||
==== `@Any` mapping
|
||||
|
||||
There is one more type of property mapping.
|
||||
The `@Any` mapping defines a polymorphic association to classes from multiple tables.
|
||||
This type of mapping requires more than one column.
|
||||
The first column contains the type of the associated entity.
|
||||
The remaining columns contain the identifier.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is impossible to specify a foreign key constraint for this kind of association.
|
||||
This is not the usual way of mapping polymorphic associations and you should use this only in special cases (e.g. audit logs, user session data, etc).
|
||||
====
|
||||
|
||||
The `@Any` annotation describes the column holding the metadata information.
|
||||
To link the value of the metadata information and an actual entity type, the `@AnyDef` and `@AnyDefs` annotations are used.
|
||||
The `metaType` attribute allows the application to specify a custom type that maps database column values to persistent classes that have identifier properties of the type specified by `idType`.
|
||||
You must specify the mapping from values of the `metaType` to class names.
|
||||
|
||||
For the next examples, consider the following `Property` class hierarchy:
|
||||
|
||||
[[mapping-column-any-property-example]]
|
||||
.`Property` class hierarchy
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/Property.java[tags=mapping-column-any-property-example]
|
||||
|
||||
include::{sourcedir}/basic/any/IntegerProperty.java[tags=mapping-column-any-property-example]
|
||||
|
||||
include::{sourcedir}/basic/any/StringProperty.java[tags=mapping-column-any-property-example]
|
||||
----
|
||||
====
|
||||
|
||||
A `PropertyHolder` can reference any such property, and, because each `Property` belongs to a separate table, the `@Any` annotation is, therefore, required.
|
||||
|
||||
[[mapping-column-any-example]]
|
||||
.`@Any` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/PropertyHolder.java[tags=mapping-column-any-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-any-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
As you can see, there are two columns used to reference a `Property` instance: `property_id` and `property_type`.
|
||||
The `property_id` is used to match the `id` column of either the `string_property` or `integer_property` tables,
|
||||
while the `property_type` is used to match the `string_property` or the `integer_property` table.
|
||||
|
||||
The table resolving mapping is defined by the `metaDef` attribute which references an `@AnyMetaDef` mapping.
|
||||
Although the `@AnyMetaDef` mapping could be set right next to the `@Any` annotation,
|
||||
it's good practice to reuse it, therefore it makes sense to configure it on a class or package-level basis.
|
||||
|
||||
The `package-info.java` contains the `@AnyMetaDef` mapping:
|
||||
|
||||
[[mapping-column-any-meta-def-example]]
|
||||
.`@Any` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/package-info.java[tags=mapping-column-any-meta-def-example]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is recommended to place the `@AnyMetaDef` mapping as a package metadata.
|
||||
====
|
||||
|
||||
To see the `@Any` annotation in action, consider the next examples.
|
||||
|
||||
If we persist an `IntegerProperty` as well as a `StringProperty` entity, and associate
|
||||
the `StringProperty` entity with a `PropertyHolder`,
|
||||
Hibernate will generate the following SQL queries:
|
||||
|
||||
[[mapping-column-any-persist-example]]
|
||||
.`@Any` mapping persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/AnyTest.java[tags=mapping-column-any-persist-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-any-persist-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `PropertyHolder` entity and navigating its `property` association,
|
||||
Hibernate will fetch the associated `StringProperty` entity like this:
|
||||
|
||||
[[mapping-column-any-query-example]]
|
||||
.`@Any` mapping query example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/AnyTest.java[tags=mapping-column-any-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-any-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-column-many-to-any]]
|
||||
===== `@ManyToAny` mapping
|
||||
|
||||
The `@Any` mapping is useful to emulate a `@ManyToOne` association when there can be multiple target entities.
|
||||
To emulate a `@OneToMany` association, the `@ManyToAny` annotation must be used.
|
||||
|
||||
In the following example, the `PropertyRepository` entity has a collection of `Property` entities.
|
||||
|
||||
The `repository_properties` link table holds the associations between `PropertyRepository` and `Property` entities.
|
||||
|
||||
[[mapping-column-many-to-any-example]]
|
||||
.`@ManyToAny` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/PropertyRepository.java[tags=mapping-column-many-to-any-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-many-to-any-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
To see the `@ManyToAny` annotation in action, consider the next examples.
|
||||
|
||||
If we persist an `IntegerProperty` as well as a `StringProperty` entity,
|
||||
and associate both of them with a `PropertyRepository` parent entity,
|
||||
Hibernate will generate the following SQL queries:
|
||||
|
||||
[[mapping-column-many-to-any-persist-example]]
|
||||
.`@ManyToAny` mapping persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/ManyToAnyTest.java[tags=mapping-column-many-to-any-persist-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-many-to-any-persist-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `PropertyRepository` entity and navigating its `properties` association,
|
||||
Hibernate will fetch the associated `IntegerProperty` and `StringProperty` entities like this:
|
||||
|
||||
[[mapping-column-many-to-any-query-example]]
|
||||
.`@ManyToAny` mapping query example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/any/ManyToAnyTest.java[tags=mapping-column-many-to-any-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-column-many-to-any-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[mapping-JoinFormula]]
|
||||
==== `@JoinFormula` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinFormula.html[`@JoinFormula`] annotation is used to customize the join between a child Foreign Key and a parent row Primary Key.
|
||||
|
||||
[[mapping-JoinFormula-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-JoinFormula-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The `country` association in the `User` entity is mapped by the country identifier provided by the `phoneNumber` property.
|
||||
|
||||
Considering we have the following entities:
|
||||
|
||||
[[mapping-JoinFormula-persistence-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-persistence-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `User` entities, the `country` property is mapped by the `@JoinFormula` expression:
|
||||
|
||||
[[mapping-JoinFormula-fetching-example]]
|
||||
.`@JoinFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-JoinFormula-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@JoinFormula` annotation is used to define a custom join association between the parent-child association.
|
||||
|
||||
[[mapping-JoinColumnOrFormula]]
|
||||
==== `@JoinColumnOrFormula` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinColumnOrFormula.html[`@JoinColumnOrFormula`] annotation is used to customize the join between a child Foreign Key and a parent row Primary Key when we need to take into consideration a column value as well as a `@JoinFormula`.
|
||||
|
||||
[[mapping-JoinColumnOrFormula-example]]
|
||||
.`@JoinColumnOrFormula` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinColumnOrFormulaTest.java[tags=mapping-JoinColumnOrFormula-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-JoinColumnOrFormula-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The `country` association in the `User` entity is mapped by the `language` property value and the associated `Country` `is_default` column value.
|
||||
|
||||
Considering we have the following entities:
|
||||
|
||||
[[mapping-JoinColumnOrFormula-persistence-example]]
|
||||
.`@JoinColumnOrFormula` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinColumnOrFormulaTest.java[tags=mapping-JoinColumnOrFormula-persistence-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `User` entities, the `country` property is mapped by the `@JoinColumnOrFormula` expression:
|
||||
|
||||
[[mapping-JoinColumnOrFormula-fetching-example]]
|
||||
.`@JoinColumnOrFormula` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/JoinColumnOrFormulaTest.java[tags=mapping-JoinColumnOrFormula-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-JoinColumnOrFormula-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@JoinColumnOrFormula` annotation is used to define a custom join association between the parent-child association.
|
||||
|
||||
[[mapping-Target]]
|
||||
==== `@Target` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Target.html[`@Target`] annotation is used to specify the implementation class of a given association that is mapped via an interface.
|
||||
The
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToOne.html[`@ManyToOne`],
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/OneToOne.html[`@OneToOne`],
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/OneToMany.html[`@OneToMany`], and
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToMany.html[`@ManyToMany`]
|
||||
feature a http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToOne.html#targetEntity--[`targetEntity`] attribute to specify the actual class of the entity association when an interface is used for the mapping.
|
||||
|
||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/ElementCollection.html[`@ElementCollection`] association has a http://docs.oracle.com/javaee/7/api/javax/persistence/ElementCollection.html#targetClass--[`targetClass`] attribute for the same purpose.
|
||||
|
||||
However, for simple embeddable types, there is no such construct and so you need to use the Hibernate-specific `@Target` annotation instead.
|
||||
|
||||
[[mapping-Target-example]]
|
||||
.`@Target` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/TargetTest.java[tags=mapping-Target-example]
|
||||
----
|
||||
====
|
||||
|
||||
The `coordinates` embeddable type is mapped as the `Coordinates` interface.
|
||||
However, Hibernate needs to know the actual implementation tye, which is `GPS` in this case,
|
||||
hence the `@Target` annotation is used to provide this information.
|
||||
|
||||
Assuming we have persisted the following `City` entity:
|
||||
|
||||
[[mapping-Target-persist-example]]
|
||||
.`@Target` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/TargetTest.java[tags=mapping-Target-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `City` entity, the `coordinates` property is mapped by the `@Target` expression:
|
||||
|
||||
[[mapping-Target-fetching-example]]
|
||||
.`@Target` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/TargetTest.java[tags=mapping-Target-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/basic/mapping-Target-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@Target` annotation is used to define a custom join association between the parent-child association.
|
||||
|
||||
[[mapping-Parent]]
|
||||
==== `@Parent` mapping
|
||||
|
||||
The Hibernate-specific `@Parent` annotation allows you to reference the owner entity from within an embeddable.
|
||||
|
||||
[[mapping-Parent-example]]
|
||||
.`@Parent` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/ParentTest.java[tags=mapping-Parent-example]
|
||||
----
|
||||
====
|
||||
|
||||
Assuming we have persisted the following `City` entity:
|
||||
|
||||
[[mapping-Parent-persist-example]]
|
||||
.`@Parent` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/ParentTest.java[tags=mapping-Parent-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `City` entity, the `city` property of the embeddable type acts as a back reference to the owning parent entity:
|
||||
|
||||
[[mapping-Parent-fetching-example]]
|
||||
.`@Parent` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/basic/ParentTest.java[tags=mapping-Parent-fetching-example]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@Parent` annotation is used to define the association between an embeddable type and the owning entity.
|
||||
|
@ -197,4 +197,99 @@ This usage is covered in detail in <<chapters/domain/identifiers.adoc#identifier
|
||||
[IMPORTANT]
|
||||
====
|
||||
Embeddable types that are used as collection entries, map keys or entity type identifiers cannot include their own collection mappings.
|
||||
====
|
||||
====
|
||||
|
||||
[[embeddable-Target]]
|
||||
==== `@Target` mapping
|
||||
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Target.html[`@Target`] annotation is used to specify the implementation class of a given association that is mapped via an interface.
|
||||
The
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToOne.html[`@ManyToOne`],
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/OneToOne.html[`@OneToOne`],
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/OneToMany.html[`@OneToMany`], and
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToMany.html[`@ManyToMany`]
|
||||
feature a http://docs.oracle.com/javaee/7/api/javax/persistence/ManyToOne.html#targetEntity--[`targetEntity`] attribute to specify the actual class of the entity association when an interface is used for the mapping.
|
||||
|
||||
The http://docs.oracle.com/javaee/7/api/javax/persistence/ElementCollection.html[`@ElementCollection`] association has a http://docs.oracle.com/javaee/7/api/javax/persistence/ElementCollection.html#targetClass--[`targetClass`] attribute for the same purpose.
|
||||
|
||||
However, for simple embeddable types, there is no such construct and so you need to use the Hibernate-specific `@Target` annotation instead.
|
||||
|
||||
[[embeddable-Target-example]]
|
||||
.`@Target` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/TargetTest.java[tags=embeddable-Target-example]
|
||||
----
|
||||
====
|
||||
|
||||
The `coordinates` embeddable type is mapped as the `Coordinates` interface.
|
||||
However, Hibernate needs to know the actual implementation tye, which is `GPS` in this case,
|
||||
hence the `@Target` annotation is used to provide this information.
|
||||
|
||||
Assuming we have persisted the following `City` entity:
|
||||
|
||||
[[embeddable-Target-persist-example]]
|
||||
.`@Target` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/TargetTest.java[tags=embeddable-Target-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `City` entity, the `coordinates` property is mapped by the `@Target` expression:
|
||||
|
||||
[[embeddable-Target-fetching-example]]
|
||||
.`@Target` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/TargetTest.java[tags=embeddable-Target-fetching-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/embeddable/embeddable-Target-fetching-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@Target` annotation is used to define a custom join association between the parent-child association.
|
||||
|
||||
[[embeddable-Parent]]
|
||||
==== `@Parent` mapping
|
||||
|
||||
The Hibernate-specific `@Parent` annotation allows you to reference the owner entity from within an embeddable.
|
||||
|
||||
[[embeddable-Parent-example]]
|
||||
.`@Parent` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/ParentTest.java[tags=embeddable-Parent-example]
|
||||
----
|
||||
====
|
||||
|
||||
Assuming we have persisted the following `City` entity:
|
||||
|
||||
[[embeddable-Parent-persist-example]]
|
||||
.`@Parent` persist example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/ParentTest.java[tags=embeddable-Parent-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `City` entity, the `city` property of the embeddable type acts as a back reference to the owning parent entity:
|
||||
|
||||
[[embeddable-Parent-fetching-example]]
|
||||
.`@Parent` fetching example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/ParentTest.java[tags=embeddable-Parent-fetching-example]
|
||||
----
|
||||
====
|
||||
|
||||
Therefore, the `@Parent` annotation is used to define the association between an embeddable type and the owning entity.
|
||||
|
@ -232,6 +232,380 @@ load::
|
||||
Each of these two methods defines an overloading variant accepting a `org.hibernate.LockOptions` argument.
|
||||
Locking is discussed in a separate <<chapters/locking/Locking.adoc#locking,chapter>>.
|
||||
|
||||
[[pc-filtering]]
|
||||
=== Filtering entities and associations
|
||||
|
||||
Hibernate offers two options if you want to filter entities or entity associations:
|
||||
|
||||
static (e.g. `@Where` and `@WhereJoinTable`):: which are defined at mapping time and
|
||||
cannot change at runtime.
|
||||
dynamic (e.g. `@Filter` and `@FilterJoinTable`):: which are applied and configured at runtime.
|
||||
|
||||
[[pc-where]]
|
||||
==== `@Where`
|
||||
|
||||
Sometimes, you want to filter out entities or collections using custom SQL criteria.
|
||||
This can be achieved using the `@Where` annotation, which can be applied to entities and collections.
|
||||
|
||||
[[pc-where-example]]
|
||||
.`@Where` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereTest.java[tags=pc-where-example]
|
||||
----
|
||||
====
|
||||
|
||||
If the database contains the following entities:
|
||||
|
||||
[[pc-where-persistence-example]]
|
||||
.Persisting and fetching entities with a `@Where` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereTest.java[tags=pc-where-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-where-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When executing an `Account` entity query, Hibernate is going to filter out all records that are not active.
|
||||
|
||||
[[pc-where-entity-query-example]]
|
||||
.Query entities mapped with `@Where`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereTest.java[tags=pc-where-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-where-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `debitAccounts` or the `creditAccounts` collections, Hibernate is going to apply the `@Where` clause filtering criteria to the associated child entities.
|
||||
|
||||
[[pc-where-collection-query-example]]
|
||||
.Traversing collections mapped with `@Where`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereTest.java[tags=pc-where-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-where-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[pc-where-join-table]]
|
||||
==== `@WhereJoinTable`
|
||||
|
||||
Just like `@Where` annotation, `@WhereJoinTable` is used to filter out collections using a joined table (e.g. @ManyToMany association).
|
||||
|
||||
[[pc-where-join-table-example]]
|
||||
.`@WhereJoinTable` mapping example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereJoinTableTest.java[tags=pc-where-join-table-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-where-join-table-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
In the example above, the current week `Reader` entities are included in the `currentWeekReaders` collection
|
||||
which uses the `@WhereJoinTable` annotation to filter the joined table rows according to the provided SQL clause.
|
||||
|
||||
Considering that the following two `Book_Reader` entries are added into our system:
|
||||
|
||||
[[pc-where-join-table-persist-example]]
|
||||
.`@WhereJoinTable` test data
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereJoinTableTest.java[tags=pc-where-join-table-persist-example]
|
||||
----
|
||||
====
|
||||
|
||||
When fetching the `currentWeekReaders` collection, Hibernate is going to find one one entry:
|
||||
|
||||
[[pc-where-join-table-fetch-example]]
|
||||
.`@WhereJoinTable` fetch example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/WhereJoinTableTest.java[tags=pc-where-join-table-fetch-example]
|
||||
----
|
||||
====
|
||||
|
||||
[[pc-filter]]
|
||||
==== `@Filter`
|
||||
|
||||
The `@Filter` annotation is another way to filter out entities or collections using custom SQL criteria.
|
||||
Unlike the `@Where` annotation, `@Filter` allows you to parameterize the filter clause at runtime.
|
||||
|
||||
Now, considering we have the following `Account` entity:
|
||||
|
||||
[[pc-filter-account-example]]
|
||||
.`@Filter` mapping entity-level usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-Account-example]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Notice that the `active` property is mapped to the `active_status` column.
|
||||
|
||||
This mapping was done to show you that the `@Filter` condition uses a SQL condition and not a JPQL filtering predicate.
|
||||
====
|
||||
|
||||
As already explained, we can also apply the `@Filter` annotation for collections as illustrated by the `Client` entity:
|
||||
|
||||
[[pc-filter-client-example]]
|
||||
.`@Filter` mapping collection-level usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-Client-example]
|
||||
----
|
||||
====
|
||||
|
||||
If we persist a `Client` with three associated `Account` entities,
|
||||
Hibernate will execute the following SQL statements:
|
||||
|
||||
[[pc-filter-persistence-example]]
|
||||
.Persisting and fetching entities with a `@Filter` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
By default, without explicitly enabling the filter, Hibernate is going to fetch all `Account` entities.
|
||||
|
||||
[[pc-no-filter-entity-query-example]]
|
||||
.Query entities mapped without activating the `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-no-filter-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-no-filter-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
If the filter is enabled and the filter parameter value is provided,
|
||||
then Hibernate is going to apply the filtering criteria to the associated `Account` entities.
|
||||
|
||||
[[pc-filter-entity-query-example]]
|
||||
.Query entities mapped with `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-entity-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-entity-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
Filters apply to entity queries, but not to direct fetching.
|
||||
|
||||
Therefore, in the following example, the filter is not taken into consideration when fetching an entity from the Persistence Context.
|
||||
|
||||
[[pc-filter-entity-example]]
|
||||
.Fetching entities mapped with `@Filter`
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-entity-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-entity-example.sql[]
|
||||
----
|
||||
|
||||
As you can see from the example above, contrary to an entity query, the filter does not prevent the entity from being loaded.
|
||||
====
|
||||
|
||||
Just like with entity queries, collections can be filtered as well, but only if the filter is explicitly enabled on the currently running Hibernate `Session`.
|
||||
|
||||
[[pc-no-filter-collection-query-example]]
|
||||
.Traversing collections without activating the `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-no-filter-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-no-filter-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
When activating the `@Filter` and fetching the `accounts` collections, Hibernate is going to apply the filter condition to the associated collection entries.
|
||||
|
||||
[[pc-filter-collection-query-example]]
|
||||
.Traversing collections mapped with `@Filter`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterTest.java[tags=pc-filter-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The main advantage of `@Filter` over the `@Where` clause is that the filtering criteria can be customized at runtime.
|
||||
====
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
It's not possible to combine the `@Filter` and `@Cache` collection annotations.
|
||||
This limitation is due to ensuring consistency and because the filtering information is not stored in the second-level cache.
|
||||
|
||||
If caching were allowed for a currently filtered collection, then the second-level cache would store only a subset of the whole collection.
|
||||
Afterward, every other Session will get the filtered collection from the cache, even if the Session-level filters have not been explicitly activated.
|
||||
|
||||
For this reason, the second-level collection cache is limited to storing whole collections, and not subsets.
|
||||
====
|
||||
|
||||
[[pc-filter-sql-fragment-alias]]
|
||||
==== `@Filter` with `@SqlFragmentAlias`
|
||||
|
||||
When using the `@Filter` annotation and working with entities that are mapped onto multiple database tables,
|
||||
you will need to use the
|
||||
https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/SqlFragmentAlias.html[`@SqlFragmentAlias`] annotation
|
||||
if the `@Filter` defines a condition that uses predicates across multiple tables.
|
||||
|
||||
[[pc-filter-sql-fragment-alias-example]]
|
||||
.`@SqlFragmentAlias` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterSqlFragementAliasTest.java[tags=pc-filter-sql-fragment-alias-example]
|
||||
----
|
||||
====
|
||||
|
||||
Now, when fetching the `Account` entities and activating the filter,
|
||||
Hibernate is going to apply the right table aliases to the filter predicates:
|
||||
|
||||
[[pc-filter-sql-fragment-alias-query-example]]
|
||||
.Fetching a collection filtered with `@SqlFragmentAlias`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterSqlFragementAliasTest.java[tags=pc-filter-sql-fragment-alias-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-sql-fragment-alias-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[pc-filter-join-table]]
|
||||
==== `@FilterJoinTable`
|
||||
|
||||
When using the `@Filter` annotation with collections, the filtering is done against the child entries (entities or embeddables).
|
||||
However, if you have a link table between the parent entity and the child table, then you need to use the `@FilterJoinTable` to filter child entries according to some column contained in the join table.
|
||||
|
||||
The `@FilterJoinTable` annotation can be, therefore, applied to a unidirectional `@OneToMany` collection as illustrated in the following mapping:
|
||||
|
||||
[[pc-filter-join-table-example]]
|
||||
.`@FilterJoinTable` mapping usage
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterJoinTableTest.java[tags=pc-filter-join-table-example]
|
||||
----
|
||||
====
|
||||
|
||||
The `firstAccounts` filter will allow us to get only the `Account` entities that have the `order_id`
|
||||
(which tells the position of every entry inside the `accounts` collection)
|
||||
less than a given number (e.g. `maxOrderId`).
|
||||
|
||||
Let's assume our database contains the following entities:
|
||||
|
||||
[[pc-filter-join-table-persistence-example]]
|
||||
.Persisting and fetching entities with a `@FilterJoinTable` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterJoinTableTest.java[tags=pc-filter-join-table-persistence-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-join-table-persistence-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
The collections can be filtered only if the associated filter is enabled on the currently running Hibernate `Session`.
|
||||
|
||||
[[pc-no-filter-join-table-collection-query-example]]
|
||||
.Traversing collections mapped with `@FilterJoinTable` without enabling the filter
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterJoinTableTest.java[tags=pc-no-filter-join-table-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-no-filter-join-table-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
If we enable the filter and set the `maxOrderId` to `1` when fetching the `accounts` collections, Hibernate is going to apply the `@FilterJoinTable` clause filtering criteria, and we will get just
|
||||
`2` `Account` entities, with the `order_id` values of `0` and `1`.
|
||||
|
||||
[[pc-filter-join-table-collection-query-example]]
|
||||
.Traversing collections mapped with `@FilterJoinTable`
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/FilterJoinTableTest.java[tags=pc-filter-join-table-collection-query-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-filter-join-table-collection-query-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[[pc-managed-state]]
|
||||
=== Modifying managed/persistent state
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
SELECT
|
||||
c.id as id1_1_0_,
|
||||
c.name as name2_1_0_
|
||||
FROM
|
||||
Client c
|
||||
WHERE
|
||||
c.id = 1
|
||||
|
||||
SELECT
|
||||
a.id as id1_0_,
|
||||
a.active_status as active2_0_,
|
||||
a.amount as amount3_0_,
|
||||
a.client_id as client_i6_0_,
|
||||
a.rate as rate4_0_,
|
||||
a.account_type as account_5_0_
|
||||
FROM
|
||||
Account a
|
||||
WHERE
|
||||
accounts0_.active_status = true
|
||||
and a.client_id = 1
|
@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
a.id as id1_0_0_,
|
||||
a.active_status as active2_0_0_,
|
||||
a.amount as amount3_0_0_,
|
||||
a.client_id as client_i6_0_0_,
|
||||
a.rate as rate4_0_0_,
|
||||
a.account_type as account_5_0_0_,
|
||||
c.id as id1_1_1_,
|
||||
c.name as name2_1_1_
|
||||
FROM
|
||||
Account a
|
||||
WHERE
|
||||
a.id = 2
|
@ -0,0 +1,11 @@
|
||||
SELECT
|
||||
a.id as id1_0_,
|
||||
a.active_status as active2_0_,
|
||||
a.amount as amount3_0_,
|
||||
a.client_id as client_i6_0_,
|
||||
a.rate as rate4_0_,
|
||||
a.account_type as account_5_0_
|
||||
FROM
|
||||
Account a
|
||||
WHERE
|
||||
a.active_status = true
|
@ -0,0 +1,19 @@
|
||||
SELECT
|
||||
ca.Client_id as Client_i1_2_0_,
|
||||
ca.accounts_id as accounts2_2_0_,
|
||||
ca.order_id as order_id3_0_,
|
||||
a.id as id1_0_1_,
|
||||
a.amount as amount3_0_1_,
|
||||
a.rate as rate4_0_1_,
|
||||
a.account_type as account_5_0_1_
|
||||
FROM
|
||||
Client_Account ca
|
||||
INNER JOIN
|
||||
Account a
|
||||
ON ca.accounts_id=a.id
|
||||
WHERE
|
||||
ca.order_id <= ?
|
||||
AND ca.Client_id = ?
|
||||
|
||||
-- binding parameter [1] as [INTEGER] - [1]
|
||||
-- binding parameter [2] as [BIGINT] - [1]
|
@ -0,0 +1,23 @@
|
||||
INSERT INTO Client (name, id)
|
||||
VALUES ('John Doe', 1)
|
||||
|
||||
INSERT INTO Account (amount, client_id, rate, account_type, id)
|
||||
VALUES (5000.0, 1, 0.0125, 'CREDIT', 1)
|
||||
|
||||
INSERT INTO Account (amount, client_id, rate, account_type, id)
|
||||
VALUES (0.0, 1, 0.0105, 'DEBIT', 2)
|
||||
|
||||
INSERT INTO Account (amount, client_id, rate, account_type, id)
|
||||
VALUES (250.0, 1, 0.0105, 'DEBIT', 3)
|
||||
|
||||
INSERT INTO Client_Account (Client_id, order_id, accounts_id)
|
||||
VALUES (1, 0, 1)
|
||||
|
||||
INSERT INTO Client_Account (Client_id, order_id, accounts_id)
|
||||
VALUES (1, 0, 1)
|
||||
|
||||
INSERT INTO Client_Account (Client_id, order_id, accounts_id)
|
||||
VALUES (1, 1, 2)
|
||||
|
||||
INSERT INTO Client_Account (Client_id, order_id, accounts_id)
|
||||
VALUES (1, 2, 3)
|
@ -0,0 +1,11 @@
|
||||
INSERT INTO Client (name, id)
|
||||
VALUES ('John Doe', 1)
|
||||
|
||||
INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
|
||||
VALUES (true, 5000.0, 1, 0.0125, 'CREDIT', 1)
|
||||
|
||||
INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
|
||||
VALUES (false, 0.0, 1, 0.0105, 'DEBIT', 2)
|
||||
|
||||
INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
|
||||
VALUES (true, 250.0, 1, 0.0105, 'DEBIT', 3)
|
@ -0,0 +1,16 @@
|
||||
select
|
||||
filtersqlf0_.id as id1_0_,
|
||||
filtersqlf0_.active as active2_0_,
|
||||
filtersqlf0_.amount as amount3_0_,
|
||||
filtersqlf0_.rate as rate4_0_,
|
||||
filtersqlf0_1_.deleted as deleted1_1_
|
||||
from
|
||||
account filtersqlf0_
|
||||
left outer join
|
||||
account_details filtersqlf0_1_
|
||||
on filtersqlf0_.id=filtersqlf0_1_.id
|
||||
where
|
||||
filtersqlf0_.active = ?
|
||||
and filtersqlf0_1_.deleted = false
|
||||
|
||||
-- binding parameter [1] as [BOOLEAN] - [true]
|
@ -0,0 +1,19 @@
|
||||
SELECT
|
||||
c.id as id1_1_0_,
|
||||
c.name as name2_1_0_
|
||||
FROM
|
||||
Client c
|
||||
WHERE
|
||||
c.id = 1
|
||||
|
||||
SELECT
|
||||
a.id as id1_0_,
|
||||
a.active_status as active2_0_,
|
||||
a.amount as amount3_0_,
|
||||
a.client_id as client_i6_0_,
|
||||
a.rate as rate4_0_,
|
||||
a.account_type as account_5_0_
|
||||
FROM
|
||||
Account a
|
||||
WHERE
|
||||
a.client_id = 1
|
@ -0,0 +1,9 @@
|
||||
SELECT
|
||||
a.id as id1_0_,
|
||||
a.active_status as active2_0_,
|
||||
a.amount as amount3_0_,
|
||||
a.client_id as client_i6_0_,
|
||||
a.rate as rate4_0_,
|
||||
a.account_type as account_5_0_
|
||||
FROM
|
||||
Account a
|
@ -0,0 +1,17 @@
|
||||
SELECT
|
||||
ca.Client_id as Client_i1_2_0_,
|
||||
ca.accounts_id as accounts2_2_0_,
|
||||
ca.order_id as order_id3_0_,
|
||||
a.id as id1_0_1_,
|
||||
a.amount as amount3_0_1_,
|
||||
a.rate as rate4_0_1_,
|
||||
a.account_type as account_5_0_1_
|
||||
FROM
|
||||
Client_Account ca
|
||||
INNER JOIN
|
||||
Account a
|
||||
ON ca.accounts_id=a.id
|
||||
WHERE
|
||||
ca.Client_id = ?
|
||||
|
||||
-- binding parameter [1] as [BIGINT] - [1]
|
@ -0,0 +1,25 @@
|
||||
SELECT
|
||||
c.client_id as client_i6_0_0_,
|
||||
c.id as id1_0_0_,
|
||||
c.id as id1_0_1_,
|
||||
c.active as active2_0_1_,
|
||||
c.amount as amount3_0_1_,
|
||||
c.client_id as client_i6_0_1_,
|
||||
c.rate as rate4_0_1_,
|
||||
c.account_type as account_5_0_1_
|
||||
FROM
|
||||
Account c
|
||||
WHERE ( c.active = true and c.account_type = 'CREDIT' ) AND c.client_id = 1
|
||||
|
||||
SELECT
|
||||
d.client_id as client_i6_0_0_,
|
||||
d.id as id1_0_0_,
|
||||
d.id as id1_0_1_,
|
||||
d.active as active2_0_1_,
|
||||
d.amount as amount3_0_1_,
|
||||
d.client_id as client_i6_0_1_,
|
||||
d.rate as rate4_0_1_,
|
||||
d.account_type as account_5_0_1_
|
||||
FROM
|
||||
Account d
|
||||
WHERE ( d.active = true and d.account_type = 'DEBIT' ) AND d.client_id = 1
|
@ -0,0 +1,10 @@
|
||||
SELECT
|
||||
a.id as id1_0_,
|
||||
a.active as active2_0_,
|
||||
a.amount as amount3_0_,
|
||||
a.client_id as client_i6_0_,
|
||||
a.rate as rate4_0_,
|
||||
a.account_type as account_5_0_
|
||||
FROM
|
||||
Account a
|
||||
WHERE ( a.active = true )
|
@ -0,0 +1,31 @@
|
||||
create table Book (
|
||||
id bigint not null,
|
||||
author varchar(255),
|
||||
title varchar(255),
|
||||
primary key (id)
|
||||
)
|
||||
|
||||
create table Book_Reader (
|
||||
book_id bigint not null,
|
||||
reader_id bigint not null
|
||||
)
|
||||
|
||||
create table Reader (
|
||||
id bigint not null,
|
||||
name varchar(255),
|
||||
primary key (id)
|
||||
)
|
||||
|
||||
alter table Book_Reader
|
||||
add constraint FKsscixgaa5f8lphs9bjdtpf9g
|
||||
foreign key (reader_id)
|
||||
references Reader
|
||||
|
||||
alter table Book_Reader
|
||||
add constraint FKoyrwu9tnwlukd1616qhck21ra
|
||||
foreign key (book_id)
|
||||
references Book
|
||||
|
||||
alter table Book_Reader
|
||||
add created_on timestamp
|
||||
default current_timestamp
|
@ -0,0 +1,11 @@
|
||||
INSERT INTO Client (name, id)
|
||||
VALUES ('John Doe', 1)
|
||||
|
||||
INSERT INTO Account (active, amount, client_id, rate, account_type, id)
|
||||
VALUES (true, 5000.0, 1, 0.0125, 'CREDIT', 1)
|
||||
|
||||
INSERT INTO Account (active, amount, client_id, rate, account_type, id)
|
||||
VALUES (false, 0.0, 1, 0.0105, 'DEBIT', 2)
|
||||
|
||||
INSERT INTO Account (active, amount, client_id, rate, account_type, id)
|
||||
VALUES (true, 250.0, 1, 0.0105, 'DEBIT', 3)
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.associations;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
@ -41,7 +41,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::mapping-JoinColumnOrFormula-persistence-example[]
|
||||
//tag::associations-JoinColumnOrFormula-persistence-example[]
|
||||
Country US = new Country();
|
||||
US.setId( 1 );
|
||||
US.setDefault( true );
|
||||
@ -75,9 +75,9 @@ public void testLifecycle() {
|
||||
entityManager.persist( user2 );
|
||||
|
||||
} );
|
||||
//end::mapping-JoinColumnOrFormula-persistence-example[]
|
||||
//end::associations-JoinColumnOrFormula-persistence-example[]
|
||||
|
||||
//tag::mapping-JoinColumnOrFormula-fetching-example[]
|
||||
//tag::associations-JoinColumnOrFormula-fetching-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.info( "Fetch User entities" );
|
||||
|
||||
@ -87,10 +87,10 @@ public void testLifecycle() {
|
||||
User vlad = entityManager.find( User.class, 2L );
|
||||
assertEquals( Romania, vlad.getCountry());
|
||||
} );
|
||||
//end::mapping-JoinColumnOrFormula-fetching-example[]
|
||||
//end::associations-JoinColumnOrFormula-fetching-example[]
|
||||
}
|
||||
|
||||
//tag::mapping-JoinColumnOrFormula-example[]
|
||||
//tag::associations-JoinColumnOrFormula-example[]
|
||||
@Entity(name = "User")
|
||||
@Table(name = "users")
|
||||
public static class User {
|
||||
@ -123,7 +123,7 @@ public static class User {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-JoinColumnOrFormula-example[]
|
||||
//end::associations-JoinColumnOrFormula-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -164,11 +164,11 @@ public void setCountry(Country country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
//tag::mapping-JoinColumnOrFormula-example[]
|
||||
//tag::associations-JoinColumnOrFormula-example[]
|
||||
}
|
||||
//end::mapping-JoinColumnOrFormula-example[]
|
||||
//end::associations-JoinColumnOrFormula-example[]
|
||||
|
||||
//tag::mapping-JoinColumnOrFormula-example[]
|
||||
//tag::associations-JoinColumnOrFormula-example[]
|
||||
|
||||
@Entity(name = "Country")
|
||||
@Table(name = "countries")
|
||||
@ -186,7 +186,7 @@ public static class Country implements Serializable {
|
||||
|
||||
//Getters and setters, equals and hashCode methods omitted for brevity
|
||||
|
||||
//end::mapping-JoinColumnOrFormula-example[]
|
||||
//end::associations-JoinColumnOrFormula-example[]
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
@ -236,7 +236,7 @@ public boolean equals(Object o) {
|
||||
public int hashCode() {
|
||||
return Objects.hash( getId() );
|
||||
}
|
||||
//tag::mapping-JoinColumnOrFormula-example[]
|
||||
//tag::associations-JoinColumnOrFormula-example[]
|
||||
}
|
||||
//end::mapping-JoinColumnOrFormula-example[]
|
||||
//end::associations-JoinColumnOrFormula-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.associations;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.persistence.Entity;
|
||||
@ -40,7 +40,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::mapping-JoinFormula-persistence-example[]
|
||||
//tag::associations-JoinFormula-persistence-example[]
|
||||
Country US = new Country();
|
||||
US.setId( 1 );
|
||||
US.setName( "United States" );
|
||||
@ -69,9 +69,9 @@ public void testLifecycle() {
|
||||
user2.setPhoneNumber( "+40-123-4567" );
|
||||
entityManager.persist( user2 );
|
||||
} );
|
||||
//end::mapping-JoinFormula-persistence-example[]
|
||||
//end::associations-JoinFormula-persistence-example[]
|
||||
|
||||
//tag::mapping-JoinFormula-fetching-example[]
|
||||
//tag::associations-JoinFormula-fetching-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.info( "Fetch User entities" );
|
||||
|
||||
@ -81,10 +81,10 @@ public void testLifecycle() {
|
||||
User vlad = entityManager.find( User.class, 2L );
|
||||
assertEquals( Romania, vlad.getCountry());
|
||||
} );
|
||||
//end::mapping-JoinFormula-fetching-example[]
|
||||
//end::associations-JoinFormula-fetching-example[]
|
||||
}
|
||||
|
||||
//tag::mapping-JoinFormula-example[]
|
||||
//tag::associations-JoinFormula-example[]
|
||||
@Entity(name = "User")
|
||||
@Table(name = "users")
|
||||
public static class User {
|
||||
@ -104,7 +104,7 @@ public static class User {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-JoinFormula-example[]
|
||||
//end::associations-JoinFormula-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -141,11 +141,11 @@ public Country getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
//tag::mapping-JoinFormula-example[]
|
||||
//tag::associations-JoinFormula-example[]
|
||||
}
|
||||
//end::mapping-JoinFormula-example[]
|
||||
//end::associations-JoinFormula-example[]
|
||||
|
||||
//tag::mapping-JoinFormula-example[]
|
||||
//tag::associations-JoinFormula-example[]
|
||||
|
||||
@Entity(name = "Country")
|
||||
@Table(name = "countries")
|
||||
@ -158,7 +158,7 @@ public static class Country {
|
||||
|
||||
//Getters and setters, equals and hashCode methods omitted for brevity
|
||||
|
||||
//end::mapping-JoinFormula-example[]
|
||||
//end::associations-JoinFormula-example[]
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
@ -192,7 +192,7 @@ public boolean equals(Object o) {
|
||||
public int hashCode() {
|
||||
return Objects.hash( getId() );
|
||||
}
|
||||
//tag::mapping-JoinFormula-example[]
|
||||
//tag::associations-JoinFormula-example[]
|
||||
}
|
||||
//end::mapping-JoinFormula-example[]
|
||||
//end::associations-JoinFormula-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
@ -37,7 +37,7 @@ protected String[] getAnnotatedPackages() {
|
||||
public void test() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
//tag::mapping-column-any-persist-example[]
|
||||
//tag::associations-any-persist-example[]
|
||||
IntegerProperty ageProperty = new IntegerProperty();
|
||||
ageProperty.setId( 1L );
|
||||
ageProperty.setName( "age" );
|
||||
@ -57,16 +57,16 @@ public void test() {
|
||||
namePropertyHolder.setProperty( nameProperty );
|
||||
|
||||
session.persist( namePropertyHolder );
|
||||
//end::mapping-column-any-persist-example[]
|
||||
//end::associations-any-persist-example[]
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
//tag::mapping-column-any-query-example[]
|
||||
//tag::associations-any-query-example[]
|
||||
PropertyHolder propertyHolder = session.get( PropertyHolder.class, 1L );
|
||||
|
||||
assertEquals("name", propertyHolder.getProperty().getName());
|
||||
assertEquals("John Doe", propertyHolder.getProperty().getValue());
|
||||
//end::mapping-column-any-query-example[]
|
||||
//end::associations-any-query-example[]
|
||||
} );
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
//tag::mapping-column-any-property-example[]
|
||||
//tag::associations-any-property-example[]
|
||||
|
||||
@Entity
|
||||
@Table(name="integer_property")
|
||||
@ -37,7 +37,7 @@ public Integer getValue() {
|
||||
}
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-column-any-property-example[]
|
||||
//end::associations-any-property-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@ -54,7 +54,7 @@ public void setName(String name) {
|
||||
public void setValue(Integer value) {
|
||||
this.value = value;
|
||||
}
|
||||
//tag::mapping-column-any-property-example[]
|
||||
//tag::associations-any-property-example[]
|
||||
}
|
||||
//end::mapping-column-any-property-example[]
|
||||
//end::associations-any-property-example[]
|
||||
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
@ -38,7 +38,7 @@ protected String[] getAnnotatedPackages() {
|
||||
public void test() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
//tag::mapping-column-many-to-any-persist-example[]
|
||||
//tag::associations-many-to-any-persist-example[]
|
||||
IntegerProperty ageProperty = new IntegerProperty();
|
||||
ageProperty.setId( 1L );
|
||||
ageProperty.setName( "age" );
|
||||
@ -60,11 +60,11 @@ public void test() {
|
||||
propertyRepository.getProperties().add( nameProperty );
|
||||
|
||||
session.persist( propertyRepository );
|
||||
//end::mapping-column-many-to-any-persist-example[]
|
||||
//end::associations-many-to-any-persist-example[]
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
//tag::mapping-column-many-to-any-query-example[]
|
||||
//tag::associations-many-to-any-query-example[]
|
||||
PropertyRepository propertyRepository = session.get( PropertyRepository.class, 1L );
|
||||
|
||||
assertEquals(2, propertyRepository.getProperties().size());
|
||||
@ -72,7 +72,7 @@ public void test() {
|
||||
for(Property property : propertyRepository.getProperties()) {
|
||||
assertNotNull( property.getValue() );
|
||||
}
|
||||
//end::mapping-column-many-to-any-query-example[]
|
||||
//end::associations-many-to-any-query-example[]
|
||||
} );
|
||||
}
|
||||
|
@ -4,13 +4,13 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
//tag::mapping-column-any-property-example[]
|
||||
//tag::associations-any-property-example[]
|
||||
public interface Property<T> {
|
||||
|
||||
String getName();
|
||||
|
||||
T getValue();
|
||||
}
|
||||
//end::mapping-column-any-property-example[]
|
||||
//end::associations-any-property-example[]
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
import org.hibernate.annotations.Any;
|
||||
|
||||
//tag::mapping-column-any-example[]
|
||||
//tag::associations-any-example[]
|
||||
@Entity
|
||||
@Table( name = "property_holder" )
|
||||
public class PropertyHolder {
|
||||
@ -31,7 +31,7 @@ public class PropertyHolder {
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
|
||||
//end::mapping-column-any-example[]
|
||||
//end::associations-any-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -47,6 +47,6 @@ public Property getProperty() {
|
||||
public void setProperty(Property property) {
|
||||
this.property = property;
|
||||
}
|
||||
//tag::mapping-column-any-example[]
|
||||
//tag::associations-any-example[]
|
||||
}
|
||||
//end::mapping-column-any-example[]
|
||||
//end::associations-any-example[]
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -18,7 +18,7 @@
|
||||
import org.hibernate.annotations.Cascade;
|
||||
import org.hibernate.annotations.ManyToAny;
|
||||
|
||||
//tag::mapping-column-many-to-any-example[]
|
||||
//tag::associations-many-to-any-example[]
|
||||
@Entity
|
||||
@Table( name = "property_repository" )
|
||||
public class PropertyRepository {
|
||||
@ -39,7 +39,7 @@ public class PropertyRepository {
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
|
||||
//end::mapping-column-many-to-any-example[]
|
||||
//end::associations-many-to-any-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -52,6 +52,6 @@ public List<Property<?>> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
//tag::mapping-column-many-to-any-example[]
|
||||
//tag::associations-many-to-any-example[]
|
||||
}
|
||||
//end::mapping-column-many-to-any-example[]
|
||||
//end::associations-many-to-any-example[]
|
@ -4,14 +4,14 @@
|
||||
* 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.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
//tag::mapping-column-any-property-example[]
|
||||
//tag::associations-any-property-example[]
|
||||
|
||||
@Entity
|
||||
@Table(name="string_property")
|
||||
@ -37,7 +37,7 @@ public String getValue() {
|
||||
}
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-column-any-property-example[]
|
||||
//end::associations-any-property-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@ -54,6 +54,6 @@ public void setName(String name) {
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
//tag::mapping-column-any-property-example[]
|
||||
//tag::associations-any-property-example[]
|
||||
}
|
||||
//end::mapping-column-any-property-example[]
|
||||
//end::associations-any-property-example[]
|
@ -6,16 +6,16 @@
|
||||
*/
|
||||
|
||||
// $Id$
|
||||
//tag::mapping-column-any-meta-def-example[]
|
||||
//tag::associations-any-meta-def-example[]
|
||||
@AnyMetaDef( name= "PropertyMetaDef", metaType = "string", idType = "long",
|
||||
metaValues = {
|
||||
@MetaValue(value = "S", targetEntity = StringProperty.class),
|
||||
@MetaValue(value = "I", targetEntity = IntegerProperty.class)
|
||||
}
|
||||
)
|
||||
package org.hibernate.userguide.mapping.basic.any;
|
||||
package org.hibernate.userguide.associations.any;
|
||||
|
||||
import org.hibernate.annotations.AnyMetaDef;
|
||||
import org.hibernate.annotations.MetaValue;
|
||||
//end::mapping-column-any-meta-def-example[]
|
||||
//end::associations-any-meta-def-example[]
|
||||
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.userguide.mapping.embeddable;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.Parent;
|
||||
import org.hibernate.annotations.Target;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class ParentTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
City.class,
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::embeddable-Parent-persist-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
City cluj = new City();
|
||||
cluj.setName( "Cluj" );
|
||||
cluj.setCoordinates( new GPS( 46.77120, 23.62360 ) );
|
||||
|
||||
entityManager.persist( cluj );
|
||||
} );
|
||||
//end::embeddable-Parent-persist-example[]
|
||||
|
||||
|
||||
//tag::embeddable-Parent-fetching-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
City cluj = entityManager.find( City.class, 1L );
|
||||
|
||||
assertSame( cluj, cluj.getCoordinates().getCity() );
|
||||
} );
|
||||
//end::embeddable-Parent-fetching-example[]
|
||||
}
|
||||
|
||||
//tag::embeddable-Parent-example[]
|
||||
|
||||
@Embeddable
|
||||
public static class GPS {
|
||||
|
||||
private double latitude;
|
||||
|
||||
private double longitude;
|
||||
|
||||
@Parent
|
||||
private City city;
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::embeddable-Parent-example[]
|
||||
|
||||
private GPS() {
|
||||
}
|
||||
|
||||
public GPS(double latitude, double longitude) {
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public City getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(City city) {
|
||||
this.city = city;
|
||||
}
|
||||
//tag::embeddable-Parent-example[]
|
||||
}
|
||||
//end::embeddable-Parent-example[]
|
||||
|
||||
//tag::embeddable-Parent-example[]
|
||||
|
||||
@Entity(name = "City")
|
||||
public static class City {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Embedded
|
||||
@Target( GPS.class )
|
||||
private GPS coordinates;
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::embeddable-Parent-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public GPS getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public void setCoordinates(GPS coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
}
|
||||
//tag::embeddable-Parent-example[]
|
||||
}
|
||||
//end::embeddable-Parent-example[]
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.userguide.mapping.embeddable;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.annotations.Target;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class TargetTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
City.class,
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::embeddable-Target-persist-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
City cluj = new City();
|
||||
cluj.setName( "Cluj" );
|
||||
cluj.setCoordinates( new GPS( 46.77120, 23.62360 ) );
|
||||
|
||||
entityManager.persist( cluj );
|
||||
} );
|
||||
//end::embeddable-Target-persist-example[]
|
||||
|
||||
|
||||
//tag::embeddable-Target-fetching-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
City cluj = entityManager.find( City.class, 1L );
|
||||
|
||||
assertEquals( 46.77120, cluj.getCoordinates().x(), 0.00001 );
|
||||
assertEquals( 23.62360, cluj.getCoordinates().y(), 0.00001 );
|
||||
} );
|
||||
//end::embeddable-Target-fetching-example[]
|
||||
}
|
||||
|
||||
//tag::embeddable-Target-example[]
|
||||
public interface Coordinates {
|
||||
double x();
|
||||
double y();
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class GPS implements Coordinates {
|
||||
|
||||
private double latitude;
|
||||
|
||||
private double longitude;
|
||||
|
||||
private GPS() {
|
||||
}
|
||||
|
||||
public GPS(double latitude, double longitude) {
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double x() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double y() {
|
||||
return longitude;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "City")
|
||||
public static class City {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Embedded
|
||||
@Target( GPS.class )
|
||||
private Coordinates coordinates;
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::embeddable-Target-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Coordinates getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public void setCoordinates(Coordinates coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
}
|
||||
//tag::embeddable-Target-example[]
|
||||
}
|
||||
//end::embeddable-Target-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.pc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -47,7 +47,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::mapping-filter-join-table-persistence-example[]
|
||||
//tag::pc-filter-join-table-persistence-example[]
|
||||
Client client = new Client()
|
||||
.setId( 1L )
|
||||
.setName( "John Doe" );
|
||||
@ -77,21 +77,21 @@ public void testLifecycle() {
|
||||
);
|
||||
|
||||
entityManager.persist( client );
|
||||
//end::mapping-filter-join-table-persistence-example[]
|
||||
//end::pc-filter-join-table-persistence-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::mapping-no-filter-join-table-collection-query-example[]
|
||||
//tag::pc-no-filter-join-table-collection-query-example[]
|
||||
Client client = entityManager.find( Client.class, 1L );
|
||||
|
||||
assertEquals( 3, client.getAccounts().size());
|
||||
//end::mapping-no-filter-join-table-collection-query-example[]
|
||||
//end::pc-no-filter-join-table-collection-query-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.infof( "Activate filter [%s]", "firstAccounts");
|
||||
|
||||
//tag::mapping-filter-join-table-collection-query-example[]
|
||||
//tag::pc-filter-join-table-collection-query-example[]
|
||||
Client client = entityManager.find( Client.class, 1L );
|
||||
|
||||
entityManager
|
||||
@ -100,7 +100,7 @@ public void testLifecycle() {
|
||||
.setParameter( "maxOrderId", 1);
|
||||
|
||||
assertEquals( 2, client.getAccounts().size());
|
||||
//end::mapping-filter-join-table-collection-query-example[]
|
||||
//end::pc-filter-join-table-collection-query-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ public enum AccountType {
|
||||
CREDIT
|
||||
}
|
||||
|
||||
//tag::mapping-filter-join-table-example[]
|
||||
//tag::pc-filter-join-table-example[]
|
||||
@Entity(name = "Client")
|
||||
@FilterDef(
|
||||
name="firstAccounts",
|
||||
@ -138,7 +138,7 @@ public static class Client {
|
||||
private List<Account> accounts = new ArrayList<>( );
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-filter-join-table-example[]
|
||||
//end::pc-filter-join-table-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -160,7 +160,7 @@ public Client setName(String name) {
|
||||
public List<Account> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
//tag::mapping-filter-join-table-example[]
|
||||
//tag::pc-filter-join-table-example[]
|
||||
|
||||
public void addAccount(Account account) {
|
||||
this.accounts.add( account );
|
||||
@ -182,7 +182,7 @@ public static class Account {
|
||||
private Double rate;
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-filter-join-table-example[]
|
||||
//end::pc-filter-join-table-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -219,7 +219,7 @@ public Account setRate(Double rate) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//tag::mapping-filter-join-table-example[]
|
||||
//tag::pc-filter-join-table-example[]
|
||||
}
|
||||
//end::mapping-filter-join-table-example[]
|
||||
//end::pc-filter-join-table-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.pc;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
@ -81,7 +81,7 @@ public void testLifecycle() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.infof( "Activate filter [%s]", "activeAccount");
|
||||
|
||||
//tag::mapping-filter-sql-fragment-alias-query-example[]
|
||||
//tag::pc-filter-sql-fragment-alias-query-example[]
|
||||
entityManager
|
||||
.unwrap( Session.class )
|
||||
.enableFilter( "activeAccount" )
|
||||
@ -90,12 +90,12 @@ public void testLifecycle() {
|
||||
List<Account> accounts = entityManager.createQuery(
|
||||
"select a from Account a", Account.class)
|
||||
.getResultList();
|
||||
//end::mapping-filter-sql-fragment-alias-query-example[]
|
||||
//end::pc-filter-sql-fragment-alias-query-example[]
|
||||
assertEquals( 2, accounts.size());
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::mapping-filter-sql-fragment-alias-example[]
|
||||
//tag::pc-filter-sql-fragment-alias-example[]
|
||||
@Entity(name = "Account")
|
||||
@Table(name = "account")
|
||||
@SecondaryTable(
|
||||
@ -135,7 +135,7 @@ public static class Account {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-filter-sql-fragment-alias-example[]
|
||||
//end::pc-filter-sql-fragment-alias-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -168,7 +168,7 @@ public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
//tag::mapping-filter-sql-fragment-alias-example[]
|
||||
//tag::pc-filter-sql-fragment-alias-example[]
|
||||
}
|
||||
//end::mapping-filter-sql-fragment-alias-example[]
|
||||
//end::pc-filter-sql-fragment-alias-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.pc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -53,7 +53,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
public void testLifecycle() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
//tag::mapping-filter-persistence-example[]
|
||||
//tag::pc-filter-persistence-example[]
|
||||
Client client = new Client()
|
||||
.setId( 1L )
|
||||
.setName( "John Doe" );
|
||||
@ -86,7 +86,7 @@ public void testLifecycle() {
|
||||
);
|
||||
|
||||
entityManager.persist( client );
|
||||
//end::mapping-filter-persistence-example[]
|
||||
//end::pc-filter-persistence-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
@ -129,7 +129,7 @@ public void testLifecycle() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.infof( "Activate filter [%s]", "activeAccount");
|
||||
//tag::mapping-filter-entity-example[]
|
||||
//tag::pc-filter-entity-example[]
|
||||
entityManager
|
||||
.unwrap( Session.class )
|
||||
.enableFilter( "activeAccount" )
|
||||
@ -138,22 +138,22 @@ public void testLifecycle() {
|
||||
Account account = entityManager.find( Account.class, 2L );
|
||||
|
||||
assertFalse( account.isActive() );
|
||||
//end::mapping-filter-entity-example[]
|
||||
//end::pc-filter-entity-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::mapping-no-filter-entity-query-example[]
|
||||
//tag::pc-no-filter-entity-query-example[]
|
||||
List<Account> accounts = entityManager.createQuery(
|
||||
"select a from Account a", Account.class)
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 3, accounts.size());
|
||||
//end::mapping-no-filter-entity-query-example[]
|
||||
//end::pc-no-filter-entity-query-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.infof( "Activate filter [%s]", "activeAccount");
|
||||
//tag::mapping-filter-entity-query-example[]
|
||||
//tag::pc-filter-entity-query-example[]
|
||||
entityManager
|
||||
.unwrap( Session.class )
|
||||
.enableFilter( "activeAccount" )
|
||||
@ -164,21 +164,21 @@ public void testLifecycle() {
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 2, accounts.size());
|
||||
//end::mapping-filter-entity-query-example[]
|
||||
//end::pc-filter-entity-query-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::mapping-no-filter-collection-query-example[]
|
||||
//tag::pc-no-filter-collection-query-example[]
|
||||
Client client = entityManager.find( Client.class, 1L );
|
||||
|
||||
assertEquals( 3, client.getAccounts().size() );
|
||||
//end::mapping-no-filter-collection-query-example[]
|
||||
//end::pc-no-filter-collection-query-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
log.infof( "Activate filter [%s]", "activeAccount");
|
||||
|
||||
//tag::mapping-filter-collection-query-example[]
|
||||
//tag::pc-filter-collection-query-example[]
|
||||
entityManager
|
||||
.unwrap( Session.class )
|
||||
.enableFilter( "activeAccount" )
|
||||
@ -187,7 +187,7 @@ public void testLifecycle() {
|
||||
Client client = entityManager.find( Client.class, 1L );
|
||||
|
||||
assertEquals( 2, client.getAccounts().size() );
|
||||
//end::mapping-filter-collection-query-example[]
|
||||
//end::pc-filter-collection-query-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ public enum AccountType {
|
||||
CREDIT
|
||||
}
|
||||
|
||||
//tag::mapping-filter-Client-example[]
|
||||
//tag::pc-filter-Client-example[]
|
||||
@Entity(name = "Client")
|
||||
public static class Client {
|
||||
|
||||
@ -216,7 +216,7 @@ public static class Client {
|
||||
private List<Account> accounts = new ArrayList<>( );
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-filter-Client-example[]
|
||||
//end::pc-filter-Client-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -238,16 +238,16 @@ public Client setName(String name) {
|
||||
public List<Account> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
//tag::mapping-filter-Client-example[]
|
||||
//tag::pc-filter-Client-example[]
|
||||
|
||||
public void addAccount(Account account) {
|
||||
account.setClient( this );
|
||||
this.accounts.add( account );
|
||||
}
|
||||
}
|
||||
//end::mapping-filter-Client-example[]
|
||||
//end::pc-filter-Client-example[]
|
||||
|
||||
//tag::mapping-filter-Account-example[]
|
||||
//tag::pc-filter-Account-example[]
|
||||
@Entity(name = "Account")
|
||||
@FilterDef(
|
||||
name="activeAccount",
|
||||
@ -280,7 +280,7 @@ public static class Account {
|
||||
private boolean active;
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
//end::mapping-filter-Account-example[]
|
||||
//end::pc-filter-Account-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -335,7 +335,7 @@ public Account setActive(boolean active) {
|
||||
return this;
|
||||
}
|
||||
|
||||
//tag::mapping-filter-Account-example[]
|
||||
//tag::pc-filter-Account-example[]
|
||||
}
|
||||
//end::mapping-filter-Account-example[]
|
||||
//end::pc-filter-Account-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.pc;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
@ -42,7 +42,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::mapping-where-persistence-example[]
|
||||
//tag::pc-where-persistence-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
entityManager.unwrap( Session.class ).doWork( connection -> {
|
||||
@ -53,7 +53,7 @@ public void testLifecycle() {
|
||||
}
|
||||
} );
|
||||
|
||||
//tag::mapping-where-join-table-persist-example[]
|
||||
//tag::pc-where-join-table-persist-example[]
|
||||
Book book = new Book();
|
||||
book.setId( 1L );
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
@ -69,13 +69,13 @@ public void testLifecycle() {
|
||||
reader2.setId( 2L );
|
||||
reader2.setName( "John Doe Jr." );
|
||||
entityManager.persist( reader2 );
|
||||
//end::mapping-where-join-table-persist-example[]
|
||||
//end::pc-where-join-table-persist-example[]
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
entityManager.unwrap( Session.class ).doWork( connection -> {
|
||||
try(Statement statement = connection.createStatement()) {
|
||||
//tag::mapping-where-join-table-persist-example[]
|
||||
//tag::pc-where-join-table-persist-example[]
|
||||
|
||||
statement.executeUpdate(
|
||||
"INSERT INTO Book_Reader " +
|
||||
@ -89,18 +89,18 @@ public void testLifecycle() {
|
||||
"VALUES " +
|
||||
" (1, 2, DATEADD( 'DAY', -10, CURRENT_TIMESTAMP() )) "
|
||||
);
|
||||
//end::mapping-where-join-table-persist-example[]
|
||||
//end::pc-where-join-table-persist-example[]
|
||||
}}
|
||||
);
|
||||
|
||||
//tag::mapping-where-join-table-fetch-example[]
|
||||
//tag::pc-where-join-table-fetch-example[]
|
||||
Book book = entityManager.find( Book.class, 1L );
|
||||
assertEquals( 1, book.getCurrentWeekReaders().size() );
|
||||
//end::mapping-where-join-table-fetch-example[]
|
||||
//end::pc-where-join-table-fetch-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::mapping-where-join-table-example[]
|
||||
//tag::pc-where-join-table-example[]
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@ -122,7 +122,7 @@ public static class Book {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-where-join-table-example[]
|
||||
//end::pc-where-join-table-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -151,7 +151,7 @@ public List<Reader> getCurrentWeekReaders() {
|
||||
return currentWeekReaders;
|
||||
}
|
||||
|
||||
//tag::mapping-where-join-table-example[]
|
||||
//tag::pc-where-join-table-example[]
|
||||
}
|
||||
|
||||
@Entity(name = "Reader")
|
||||
@ -164,7 +164,7 @@ public static class Reader {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-where-join-table-example[]
|
||||
//end::pc-where-join-table-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@ -181,7 +181,7 @@ public String getName() {
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
//tag::mapping-where-join-table-example[]
|
||||
//tag::pc-where-join-table-example[]
|
||||
}
|
||||
//end::mapping-where-join-table-example[]
|
||||
//end::pc-where-join-table-example[]
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* 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.userguide.mapping.basic;
|
||||
package org.hibernate.userguide.pc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -39,7 +39,7 @@ protected Class<?>[] getAnnotatedClasses() {
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
//tag::mapping-where-persistence-example[]
|
||||
//tag::pc-where-persistence-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Client client = new Client();
|
||||
@ -77,28 +77,28 @@ public void testLifecycle() {
|
||||
client.getDebitAccounts().add( account3 );
|
||||
entityManager.persist( account3 );
|
||||
} );
|
||||
//end::mapping-where-persistence-example[]
|
||||
//end::pc-where-persistence-example[]
|
||||
|
||||
|
||||
//tag::mapping-where-entity-query-example[]
|
||||
//tag::pc-where-entity-query-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
List<Account> accounts = entityManager.createQuery(
|
||||
"select a from Account a", Account.class)
|
||||
.getResultList();
|
||||
assertEquals( 2, accounts.size());
|
||||
} );
|
||||
//end::mapping-where-entity-query-example[]
|
||||
//end::pc-where-entity-query-example[]
|
||||
|
||||
//tag::mapping-where-collection-query-example[]
|
||||
//tag::pc-where-collection-query-example[]
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Client client = entityManager.find( Client.class, 1L );
|
||||
assertEquals( 1, client.getCreditAccounts().size() );
|
||||
assertEquals( 1, client.getDebitAccounts().size() );
|
||||
} );
|
||||
//end::mapping-where-collection-query-example[]
|
||||
//end::pc-where-collection-query-example[]
|
||||
}
|
||||
|
||||
//tag::mapping-where-example[]
|
||||
//tag::pc-where-example[]
|
||||
public enum AccountType {
|
||||
DEBIT,
|
||||
CREDIT
|
||||
@ -122,7 +122,7 @@ public static class Client {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-where-example[]
|
||||
//end::pc-where-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -146,7 +146,7 @@ public List<Account> getDebitAccounts() {
|
||||
public List<Account> getCreditAccounts() {
|
||||
return creditAccounts;
|
||||
}
|
||||
//tag::mapping-where-example[]
|
||||
//tag::pc-where-example[]
|
||||
}
|
||||
|
||||
@Entity(name = "Account")
|
||||
@ -171,7 +171,7 @@ public static class Account {
|
||||
|
||||
//Getters and setters omitted for brevity
|
||||
|
||||
//end::mapping-where-example[]
|
||||
//end::pc-where-example[]
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -220,7 +220,7 @@ public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
//tag::mapping-where-example[]
|
||||
//tag::pc-where-example[]
|
||||
}
|
||||
//end::mapping-where-example[]
|
||||
//end::pc-where-example[]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user