examples in javadoc for @Any and @ManyToAny

This commit is contained in:
Gavin 2022-12-26 11:33:17 +01:00 committed by Gavin King
parent ca4474159e
commit 110a1f6a56
4 changed files with 87 additions and 15 deletions

View File

@ -22,6 +22,8 @@ import org.hibernate.annotations.AnyKeyJavaClass;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.ManyToAny;
import static org.hibernate.annotations.CascadeType.ALL;
//tag::associations-many-to-any-example[]
@Entity
@Table(name = "property_repository")
@ -36,7 +38,7 @@ public class PropertyRepository {
@AnyKeyJavaClass(Long.class)
@AnyDiscriminatorValue(discriminator = "S", entity = StringProperty.class)
@AnyDiscriminatorValue(discriminator = "I", entity = IntegerProperty.class)
@Cascade({ org.hibernate.annotations.CascadeType.ALL })
@Cascade(ALL)
@JoinTable(name = "repository_properties",
joinColumns = @JoinColumn(name = "repository_id"),
inverseJoinColumns = @JoinColumn(name = "property_id")

View File

@ -29,13 +29,35 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* An {@code @Any} mapping would store the discriminator value identifying the concrete
* type of {@code Payment} along with the state of the associated {@code Order}, instead
* of storing it with the {@code Payment} entity itself.
* <p>
* In this example, {@code Payment} would <em>not</em> be declared as an entity type, and
* would not be annotated {@link jakarta.persistence.Entity @Entity}. It might even be an
* <pre>{@code
* interface Payment { ... }
*
* @Entity
* class CashPayment { ... }
*
* @Entity
* class CreditCardPayment { ... }
*
* @Entity
* class Order {
* ...
* @Any
* @JoinColumn(name="payment_id") //the foreign key column
* @Column(name="payment_type") //the discriminator column
* @AnyDiscriminatorValue(discriminator="CASH", entity=CashPayment.class)
* @AnyDiscriminatorValue(discriminator="CREDIT", entity=CreditCardPayment.class)
* Payment payment;
* ...
* }
* }</pre>
* In this example, {@code Payment} is <em>not</em> be declared as an entity type, and
* is not annotated {@link jakarta.persistence.Entity @Entity}. It might even be an
* interface, or at most just a {@linkplain jakarta.persistence.MappedSuperclass mapped
* superclass}, of {@code CashPayment} and {@code CreditCardPayment}. So in terms of the
* object/relational mappings, {@code CashPayment} and {@code CreditCardPayment} would
* <em>not</em> be considered to participate in the same entity inheritance hierarchy.
* On the other hand, {@code CashPayment} and {@code CreditCardPayment} must have the
* same identifier type.
* <p>
* It's reasonable to think of the "foreign key" in an {@code Any} mapping is really a
* composite value made up of the foreign key and discriminator taken together. Note,
@ -44,12 +66,12 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* <ul>
* <li>{@link AnyDiscriminator}, {@link JdbcType}, or {@link JdbcTypeCode} specifies
* the type of the discriminator.
* <li>{@link AnyDiscriminatorValues} specifies how discriminator values map to entity
* <li>{@link AnyDiscriminatorValue} specifies how discriminator values map to entity
* types.
* <li>{@link jakarta.persistence.Column} or {@link Formula} specifies the column or
* formula in which the discriminator value is stored.
* <li>{@link AnyKeyJavaType}, {@link AnyKeyJavaClass}, {@link AnyKeyJdbcType}, or
* or {@link AnyKeyJdbcTypeCode} specifies the type of the foreign key.
* {@link AnyKeyJdbcTypeCode} specifies the type of the foreign key.
* <li>{@link jakarta.persistence.JoinColumn} specifies the foreign key column.
* </ul>
* Of course, {@code Any} mappings are disfavored, except in extremely special cases,
@ -62,17 +84,22 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
public @interface Any {
/**
* Defines whether the value of the field or property should be lazily loaded or must be
* eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime
* that the value must be eagerly fetched. The LAZY strategy is applied when bytecode
* enhancement is used. If not specified, defaults to EAGER.
* Specifies whether the value of the field or property may be lazily loaded or must
* be eagerly fetched:
* <ul>
* <li>{@link FetchType#EAGER EAGER} specifies that the association must be eagerly
* fetched.
* <li>{@link FetchType#LAZY LAZY} allows the association to be fetched lazily, but
* this is possible only when bytecode enhancement is used.
* </ul>
* If not explicitly specified, the default is {@code EAGER}.
*/
FetchType fetch() default FetchType.EAGER;
/**
* Whether the association is optional.
*
* If set to false then a non-null relationship must always exist.
* @return {@code false} if the association cannot be null.
*/
boolean optional() default true;
}

View File

@ -18,6 +18,14 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies the mapping of a single {@linkplain Any any}-valued
* discriminator value to its corresponding entity type.
* <p>
* This annotation may be applied:
* <ul>
* <li>directly to a field or property annotated {@link Any}, or
* <li>indirectly, as a meta-annotation, to a second annotation
* which is then applied to various fields or properties
* annotated {@link Any} with the same target entity type.
* </ul>
*
* @see Any
* @see AnyDiscriminator

View File

@ -21,10 +21,45 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* inheritance, using a discriminator value stored in an
* {@linkplain jakarta.persistence.JoinTable association table}.
* <p>
* This is just the many-valued form of {@link Any}, and the
* mapping options are similar, except that the
* {@link jakarta.persistence.JoinTable @JoinTable} annotation is
* used to specify the association table.
* The annotated property should be of type {@link java.util.List},
* {@link java.util.Set}, {@link java.util.Collection}, or
* {@link java.util.Map}, and the elements of the collection must be
* entities.
* <p>
* For example:
* <pre>{@code
* @ManyToAny
* @Column(name = "property_type")
* @AnyKeyJavaClass(Long.class)
* @AnyDiscriminatorValue(discriminator = "S", entity = StringProperty.class)
* @AnyDiscriminatorValue(discriminator = "I", entity = IntegerProperty.class)
* @JoinTable(name = "repository_properties",
* joinColumns = @JoinColumn(name = "repository_id"),
* inverseJoinColumns = @JoinColumn(name = "property_id"))
* @Cascade(PERSIST)
* private List<Property<?>> properties = new ArrayList<>();
* }</pre>
* In this example, {@code Property} is not required to be an entity type,
* it might even just be an interface, but its subtypes {@code StringProperty}
* and {@code IntegerProperty} must be entity classes with the same identifier
* type.
* <p>
* This is just the many-valued form of {@link Any}, and the mapping
* options are similar, except that the
* {@link jakarta.persistence.JoinTable @JoinTable} annotation is used
* to specify the association table.
* <ul>
* <li>{@link AnyDiscriminator}, {@link JdbcType}, or {@link JdbcTypeCode}
* specifies the type of the discriminator,
* <li>{@link AnyDiscriminatorValue} specifies how discriminator values
* map to entity types.
* <li>{@link AnyKeyJavaType}, {@link AnyKeyJavaClass}, {@link AnyKeyJdbcType},
* or {@link AnyKeyJdbcTypeCode} specifies the type of the foreign key.
* <li>{@link jakarta.persistence.JoinTable} specifies the name of the
* association table and its foreign key columns.
* <li>{@link jakarta.persistence.Column} specifies the column of the
* association table in which the discriminator value is stored.
* </ul>
*
* @see Any
*