From 110a1f6a565b9f06755c283baa7b294685d937fe Mon Sep 17 00:00:00 2001 From: Gavin Date: Mon, 26 Dec 2022 11:33:17 +0100 Subject: [PATCH] examples in javadoc for @Any and @ManyToAny --- .../associations/any/PropertyRepository.java | 4 +- .../java/org/hibernate/annotations/Any.java | 47 +++++++++++++++---- .../annotations/AnyDiscriminatorValue.java | 8 ++++ .../org/hibernate/annotations/ManyToAny.java | 43 +++++++++++++++-- 4 files changed, 87 insertions(+), 15 deletions(-) diff --git a/documentation/src/test/java/org/hibernate/userguide/associations/any/PropertyRepository.java b/documentation/src/test/java/org/hibernate/userguide/associations/any/PropertyRepository.java index 5548eda293..db06ea20d7 100644 --- a/documentation/src/test/java/org/hibernate/userguide/associations/any/PropertyRepository.java +++ b/documentation/src/test/java/org/hibernate/userguide/associations/any/PropertyRepository.java @@ -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") diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/Any.java b/hibernate-core/src/main/java/org/hibernate/annotations/Any.java index 270aa198d6..499d8bd6a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/Any.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/Any.java @@ -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. - *

- * In this example, {@code Payment} would not be declared as an entity type, and - * would not be annotated {@link jakarta.persistence.Entity @Entity}. It might even be an + *

{@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;
+ *     ...
+ * }
+ * }
+ * In this example, {@code Payment} is not 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 * not 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. *

* 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; *

* 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: + * + * 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; } diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/AnyDiscriminatorValue.java b/hibernate-core/src/main/java/org/hibernate/annotations/AnyDiscriminatorValue.java index 9d872bdd46..ce534ae5f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/AnyDiscriminatorValue.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/AnyDiscriminatorValue.java @@ -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. + *

+ * This annotation may be applied: + *

* * @see Any * @see AnyDiscriminator diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java b/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java index 2dbb016dc7..90c1a81032 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/ManyToAny.java @@ -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}. *

- * 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. + *

+ * For example: + *

{@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> properties = new ArrayList<>();
+ * }
+ * 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. + *

+ * 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. + *

* * @see Any *