Skip to content

Commit 1fa01d0

Browse files
committed
HHH-18198 -
Removed org.hibernate.annotations.Target Created new org.hibernate.annotations.TargetEmbeddable Signed-off-by: Jan Schatteman <[email protected]>
1 parent dd54cbf commit 1fa01d0

File tree

16 files changed

+96
-97
lines changed

16 files changed

+96
-97
lines changed

documentation/src/main/asciidoc/userguide/chapters/domain/embeddables.adoc

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -300,22 +300,13 @@ Embeddable types that are used as collection entries, map keys or entity type id
300300
====
301301

302302
[[embeddable-Target]]
303-
==== `@Target` mapping
303+
==== `@TargetEmbeddable` mapping
304304

305-
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.
306-
The
307-
{jpaJavadocUrlPrefix}ManyToOne.html[`@ManyToOne`],
308-
{jpaJavadocUrlPrefix}OneToOne.html[`@OneToOne`],
309-
{jpaJavadocUrlPrefix}OneToMany.html[`@OneToMany`], and
310-
{jpaJavadocUrlPrefix}ManyToMany.html[`@ManyToMany`]
311-
feature a {jpaJavadocUrlPrefix}ManyToOne.html#targetEntity--[`targetEntity`] attribute to specify the actual class of the entity association when an interface is used for the mapping.
312-
313-
The {jpaJavadocUrlPrefix}ElementCollection.html[`@ElementCollection`] association has a {jpaJavadocUrlPrefix}ElementCollection.html#targetClass--[`targetClass`] attribute for the same purpose.
314-
315-
However, for simple embeddable types, there is no such construct and so you need to use the Hibernate-specific `@Target` annotation instead.
305+
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/TargetEmbeddable.html[`@TargetEmbeddable`] annotation is used to specify the implementation class of an {jpaJavadocUrlPrefix}Embedded.html[`@Embedded`] entity property.
306+
It can therefore only be used in conjunction with `@Embedded` and needs to reference a class marked with `@Embeddable`.
316307

317308
[[embeddable-Target-example]]
318-
.`@Target` mapping usage
309+
.`@TargetEmbeddable` mapping usage
319310
====
320311
[source, java, indent=0]
321312
----
@@ -325,23 +316,23 @@ include::{example-dir-emeddable}/TargetTest.java[tags=embeddable-Target-example]
325316

326317
The `coordinates` embeddable type is mapped as the `Coordinates` interface.
327318
However, Hibernate needs to know the actual implementation type, which is `GPS` in this case,
328-
hence the `@Target` annotation is used to provide this information.
319+
hence the `@TargetEmbeddable` annotation is used to provide this information.
329320

330321
Assuming we have persisted the following `City` entity:
331322

332323
[[embeddable-Target-persist-example]]
333-
.`@Target` persist example
324+
.`@TargetEmbeddable` persist example
334325
====
335326
[source, java, indent=0]
336327
----
337328
include::{example-dir-emeddable}/TargetTest.java[tags=embeddable-Target-persist-example]
338329
----
339330
====
340331

341-
When fetching the `City` entity, the `coordinates` property is mapped by the `@Target` expression:
332+
When fetching the `City` entity, the `coordinates` property is mapped by the `@TargetEmbeddable` expression:
342333

343334
[[embeddable-Target-fetching-example]]
344-
.`@Target` fetching example
335+
.`@TargetEmbeddable` fetching example
345336
====
346337
[source, java, indent=0]
347338
----
@@ -354,7 +345,6 @@ include::{extrasdir}/embeddable/embeddable-Target-fetching-example.sql[]
354345
----
355346
====
356347

357-
Therefore, the `@Target` annotation is used to define a custom join association between the parent-child association.
358348

359349
[[embeddable-Parent]]
360350
==== `@Parent` mapping

hibernate-core/src/main/java/org/hibernate/annotations/Target.java

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.annotations;
6+
7+
import java.lang.annotation.Retention;
8+
9+
import static java.lang.annotation.ElementType.FIELD;
10+
import static java.lang.annotation.ElementType.METHOD;
11+
import static java.lang.annotation.ElementType.TYPE;
12+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
13+
14+
/**
15+
* Specifies the target type for a {@link jakarta.persistence.Embedded} entity property.
16+
* <p>
17+
* It's intended to be used exclusively in conjunction with @Embedded.
18+
*/
19+
@java.lang.annotation.Target({FIELD, METHOD, TYPE})
20+
@Retention(RUNTIME)
21+
public @interface TargetEmbeddable {
22+
/**
23+
* The target type for a {@link jakarta.persistence.Embedded} entity property
24+
*/
25+
Class<?> value();
26+
}

hibernate-core/src/main/java/org/hibernate/boot/model/internal/BasicValueBinder.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,14 +1101,6 @@ private void normalSupplementalDetails(MemberDetails attribute) {
11011101
}
11021102
}
11031103

1104-
final var targetAnn = attribute.locateAnnotationUsage( Target.class, getSourceModelContext() );
1105-
if ( targetAnn != null ) {
1106-
DEPRECATION_LOGGER.deprecatedAnnotation( Target.class, attribute.getName() );
1107-
return (BasicJavaType<?>)
1108-
typeConfiguration.getJavaTypeRegistry()
1109-
.getDescriptor( targetAnn.value() );
1110-
}
1111-
11121104
return null;
11131105
};
11141106

hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyContainer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import org.hibernate.annotations.JavaType;
1717
import org.hibernate.annotations.JdbcTypeCode;
1818
import org.hibernate.annotations.ManyToAny;
19-
import org.hibernate.annotations.Target;
19+
import org.hibernate.annotations.TargetEmbeddable;
2020
import org.hibernate.annotations.Type;
2121
import org.hibernate.boot.MappingException;
2222
import org.hibernate.boot.jaxb.Origin;
@@ -326,7 +326,7 @@ private AccessType determineLocalClassDefinedAccessStrategy() {
326326
}
327327

328328
private static boolean discoverTypeWithoutReflection(ClassDetails classDetails, MemberDetails memberDetails) {
329-
if ( memberDetails.hasDirectAnnotationUsage( Target.class ) ) {
329+
if ( memberDetails.hasDirectAnnotationUsage( TargetEmbeddable.class ) ) {
330330
return true;
331331
}
332332

hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyInferredData.java

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
package org.hibernate.boot.model.internal;
66

77
import jakarta.persistence.Access;
8+
import jakarta.persistence.Embedded;
89
import org.hibernate.MappingException;
9-
import org.hibernate.annotations.Target;
10+
import org.hibernate.annotations.TargetEmbeddable;
1011
import org.hibernate.boot.models.internal.ModelsHelper;
1112
import org.hibernate.boot.spi.AccessType;
1213
import org.hibernate.boot.spi.MetadataBuildingContext;
@@ -91,19 +92,34 @@ public TypeDetails getPropertyType() throws MappingException {
9192
return new ClassTypeDetailsImpl( classDetails, TypeDetails.Kind.CLASS );
9293
}
9394

94-
final Target legacyTargetAnnotation = propertyMember.getDirectAnnotationUsage( Target.class );
95-
if ( legacyTargetAnnotation != null ) {
96-
return resolveLegacyTargetAnnotation( legacyTargetAnnotation, sourceModelContext );
95+
final TargetEmbeddable targetEmbeddable = getTargetEmbeddableAnnotation(propertyMember);
96+
if ( targetEmbeddable != null ) {
97+
return resolveTargetEmbeddableAnnotation( targetEmbeddable, sourceModelContext );
9798
}
9899

99100
return propertyMember.resolveRelativeType( ownerType );
100101
}
101102

102-
private static ClassTypeDetailsImpl resolveLegacyTargetAnnotation(
103-
Target legacyTargetAnnotation,
103+
private TargetEmbeddable getTargetEmbeddableAnnotation(MemberDetails memberDetails) {
104+
TargetEmbeddable targetEmbeddable = memberDetails.getDirectAnnotationUsage( TargetEmbeddable.class );
105+
if ( targetEmbeddable != null ) {
106+
if (!memberDetails.hasDirectAnnotationUsage(Embedded.class) ) {
107+
// If set on an attribute, it should be an @Embedded
108+
throw new MappingException( "The @TargetEmbeddable annotation can only be set on an element marked with @Embedded" );
109+
}
110+
}
111+
else {
112+
// Set on an interface
113+
targetEmbeddable = memberDetails.getDeclaringType().getDirectAnnotationUsage( TargetEmbeddable.class );
114+
}
115+
return targetEmbeddable;
116+
}
117+
118+
private static ClassTypeDetailsImpl resolveTargetEmbeddableAnnotation(
119+
TargetEmbeddable targetEmbeddable,
104120
ModelsContext sourceModelContext) {
105121
final ClassDetailsRegistry classDetailsRegistry = sourceModelContext.getClassDetailsRegistry();
106-
final ClassDetails targetClassDetails = classDetailsRegistry.resolveClassDetails( legacyTargetAnnotation.value().getName() );
122+
final ClassDetails targetClassDetails = classDetailsRegistry.resolveClassDetails( targetEmbeddable.value().getName() );
107123
return new ClassTypeDetailsImpl( targetClassDetails, TypeDetails.Kind.CLASS );
108124
}
109125

@@ -121,9 +137,9 @@ public TypeDetails getClassOrElementType() throws MappingException {
121137
return new ClassTypeDetailsImpl( classDetails, TypeDetails.Kind.CLASS );
122138
}
123139

124-
final Target legacyTargetAnnotation = propertyMember.getDirectAnnotationUsage( Target.class );
125-
if ( legacyTargetAnnotation != null ) {
126-
return resolveLegacyTargetAnnotation( legacyTargetAnnotation, modelsContext );
140+
final TargetEmbeddable targetEmbeddable = getTargetEmbeddableAnnotation(propertyMember);
141+
if ( targetEmbeddable != null ) {
142+
return resolveTargetEmbeddableAnnotation( targetEmbeddable, modelsContext );
127143
}
128144

129145
return propertyMember.resolveRelativeAssociatedType( ownerType );
@@ -136,9 +152,9 @@ public ClassDetails getClassOrPluralElement() throws MappingException {
136152
return buildingContext.getMetadataCollector().getClassDetailsRegistry().getClassDetails( xmlTarget.value() );
137153
}
138154

139-
final Target legacyTarget = propertyMember.getDirectAnnotationUsage( Target.class );
140-
if ( legacyTarget != null ) {
141-
final String targetName = legacyTarget.value().getName();
155+
final TargetEmbeddable targetEmbeddable = getTargetEmbeddableAnnotation(propertyMember);
156+
if ( targetEmbeddable != null ) {
157+
final String targetName = targetEmbeddable.value().getName();
142158
return buildingContext.getMetadataCollector().getClassDetailsRegistry().getClassDetails( targetName );
143159
}
144160

hibernate-core/src/main/java/org/hibernate/boot/models/HibernateAnnotations.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,9 @@ public interface HibernateAnnotations {
599599
Synchronize.class,
600600
SynchronizeAnnotation.class
601601
);
602-
OrmAnnotationDescriptor<Target,TargetLegacyAnnotation> TARGET_LEGACY = new OrmAnnotationDescriptor<>(
603-
Target.class,
604-
TargetLegacyAnnotation.class
602+
OrmAnnotationDescriptor<TargetEmbeddable,TargetEmbeddableAnnotation> TARGET_EMBEDDABLE = new OrmAnnotationDescriptor<>(
603+
TargetEmbeddable.class,
604+
TargetEmbeddableAnnotation.class
605605
);
606606
SpecializedAnnotationDescriptor<TenantId,TenantIdAnnotation> TENANT_ID = new SpecializedAnnotationDescriptor<>(
607607
TenantId.class,
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,40 @@
44
*/
55
package org.hibernate.boot.models.annotations.internal;
66

7+
import org.hibernate.annotations.TargetEmbeddable;
8+
import org.hibernate.models.spi.ModelsContext;
9+
710
import java.lang.annotation.Annotation;
811
import java.util.Map;
912

10-
import org.hibernate.annotations.Target;
11-
import org.hibernate.models.spi.ModelsContext;
12-
1313
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
1414
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
15-
public class TargetLegacyAnnotation implements Target {
15+
public class TargetEmbeddableAnnotation implements TargetEmbeddable {
1616
private Class<?> value;
1717

1818
/**
1919
* Used in creating dynamic annotation instances (e.g. from XML)
2020
*/
21-
public TargetLegacyAnnotation(ModelsContext modelContext) {
21+
public TargetEmbeddableAnnotation(ModelsContext modelContext) {
2222
}
2323

2424
/**
2525
* Used in creating annotation instances from JDK variant
2626
*/
27-
public TargetLegacyAnnotation(Target annotation, ModelsContext modelContext) {
27+
public TargetEmbeddableAnnotation(TargetEmbeddable annotation, ModelsContext modelContext) {
2828
this.value = annotation.value();
2929
}
3030

3131
/**
3232
* Used in creating annotation instances from Jandex variant
3333
*/
34-
public TargetLegacyAnnotation(Map<String, Object> attributeValues, ModelsContext modelContext) {
34+
public TargetEmbeddableAnnotation(Map<String, Object> attributeValues, ModelsContext modelContext) {
3535
this.value = (Class<?>) attributeValues.get( "value" );
3636
}
3737

3838
@Override
3939
public Class<? extends Annotation> annotationType() {
40-
return Target.class;
40+
return TargetEmbeddable.class;
4141
}
4242

4343
@Override

hibernate-core/src/test/java/org/hibernate/orm/test/annotations/target/LuggageImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import jakarta.persistence.GeneratedValue;
99
import jakarta.persistence.Id;
1010

11-
import org.hibernate.annotations.Target;
11+
import org.hibernate.annotations.TargetEmbeddable;
1212

1313
/**
1414
* @author Emmanuel Bernard
@@ -21,7 +21,7 @@ public class LuggageImpl implements Luggage {
2121
private Owner owner;
2222

2323
@Embedded
24-
@Target(OwnerImpl.class)
24+
@TargetEmbeddable(OwnerImpl.class)
2525
public Owner getOwner() {
2626
return owner;
2727
}

hibernate-core/src/test/java/org/hibernate/orm/test/mapping/basic/ParentTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import jakarta.persistence.Id;
1212

1313
import org.hibernate.annotations.Parent;
14-
import org.hibernate.annotations.Target;
14+
import org.hibernate.annotations.TargetEmbeddable;
1515
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
1616

1717
import org.junit.Test;
@@ -110,7 +110,7 @@ public static class City {
110110
private String name;
111111

112112
@Embedded
113-
@Target(GPS.class)
113+
@TargetEmbeddable(GPS.class)
114114
private GPS coordinates;
115115

116116
//Getters and setters omitted for brevity

0 commit comments

Comments
 (0)